blob: b16c5f78905ceb96b6fab9a27fe55ce3286e537d [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530402 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700424};
425
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426static const audio_usecase_t offload_usecases[] = {
427 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437
Varun Balaraje49253e2017-07-06 19:48:56 +0530438static const audio_usecase_t interactive_usecases[] = {
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
447};
448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449#define STRING_TO_ENUM(string) { #string, string }
450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451struct string_to_enum {
452 const char *name;
453 uint32_t value;
454};
455
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476};
477
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700478static const struct string_to_enum formats_name_to_enum_table[] = {
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700485 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800486 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
487 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800489};
490
491//list of all supported sample rates by HDMI specification.
492static const int out_hdmi_sample_rates[] = {
493 32000, 44100, 48000, 88200, 96000, 176400, 192000,
494};
495
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700496static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800497 STRING_TO_ENUM(32000),
498 STRING_TO_ENUM(44100),
499 STRING_TO_ENUM(48000),
500 STRING_TO_ENUM(88200),
501 STRING_TO_ENUM(96000),
502 STRING_TO_ENUM(176400),
503 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800504 STRING_TO_ENUM(352800),
505 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700506};
507
Carter Hsu2e429db2019-05-14 18:50:52 +0800508struct in_effect_list {
509 struct listnode list;
510 effect_handle_t handle;
511};
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700514static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700515static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700516//cache last MBDRC cal step level
517static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530519static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
520static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700521static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800522static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530523static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530524
Derek Chen6f293672019-04-01 01:40:24 -0700525static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
526static void in_snd_mon_cb(void * stream, struct str_parms * parms);
527static void out_snd_mon_cb(void * stream, struct str_parms * parms);
528
Zhou Song331c8e52019-08-26 14:16:12 +0800529static int configure_btsco_sample_rate(snd_device_t snd_device);
530
Vatsal Buchac09ae062018-11-14 13:25:08 +0530531#ifdef AUDIO_FEATURE_ENABLED_GCOV
532extern void __gcov_flush();
533static void enable_gcov()
534{
535 __gcov_flush();
536}
537#else
538static void enable_gcov()
539{
540}
541#endif
542
justinweng20fb6d82019-02-21 18:49:00 -0700543static int in_set_microphone_direction(const struct audio_stream_in *stream,
544 audio_microphone_direction_t dir);
545static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
546
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700547static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
548 int flags __unused)
549{
550 int dir = 0;
551 switch (uc_id) {
552 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530553 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700554 dir = 1;
555 case USECASE_AUDIO_PLAYBACK_ULL:
556 break;
557 default:
558 return false;
559 }
560
561 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
562 PCM_PLAYBACK : PCM_CAPTURE);
563 if (adev->adm_is_noirq_avail)
564 return adev->adm_is_noirq_avail(adev->adm_data,
565 adev->snd_card, dev_id, dir);
566 return false;
567}
568
569static void register_out_stream(struct stream_out *out)
570{
571 struct audio_device *adev = out->dev;
572 if (is_offload_usecase(out->usecase) ||
573 !adev->adm_register_output_stream)
574 return;
575
576 // register stream first for backward compatibility
577 adev->adm_register_output_stream(adev->adm_data,
578 out->handle,
579 out->flags);
580
581 if (!adev->adm_set_config)
582 return;
583
584 if (out->realtime)
585 adev->adm_set_config(adev->adm_data,
586 out->handle,
587 out->pcm, &out->config);
588}
589
590static void register_in_stream(struct stream_in *in)
591{
592 struct audio_device *adev = in->dev;
593 if (!adev->adm_register_input_stream)
594 return;
595
596 adev->adm_register_input_stream(adev->adm_data,
597 in->capture_handle,
598 in->flags);
599
600 if (!adev->adm_set_config)
601 return;
602
603 if (in->realtime)
604 adev->adm_set_config(adev->adm_data,
605 in->capture_handle,
606 in->pcm,
607 &in->config);
608}
609
610static void request_out_focus(struct stream_out *out, long ns)
611{
612 struct audio_device *adev = out->dev;
613
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614 if (adev->adm_request_focus_v2)
615 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
616 else if (adev->adm_request_focus)
617 adev->adm_request_focus(adev->adm_data, out->handle);
618}
619
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621{
622 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700624
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700625 if (adev->adm_request_focus_v2_1)
626 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
629 else if (adev->adm_request_focus)
630 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700631
632 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700633}
634
635static void release_out_focus(struct stream_out *out)
636{
637 struct audio_device *adev = out->dev;
638
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, out->handle);
641}
642
643static void release_in_focus(struct stream_in *in)
644{
645 struct audio_device *adev = in->dev;
646 if (adev->adm_abandon_focus)
647 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
648}
649
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530650static int parse_snd_card_status(struct str_parms *parms, int *card,
651 card_status_t *status)
652{
653 char value[32]={0};
654 char state[32]={0};
655
656 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
657 if (ret < 0)
658 return -1;
659
660 // sscanf should be okay as value is of max length 32.
661 // same as sizeof state.
662 if (sscanf(value, "%d,%s", card, state) < 2)
663 return -1;
664
665 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
666 CARD_STATUS_OFFLINE;
667 return 0;
668}
669
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700670static inline void adjust_frames_for_device_delay(struct stream_out *out,
671 uint32_t *dsp_frames) {
672 // Adjustment accounts for A2dp encoder latency with offload usecases
673 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800674 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700675 unsigned long offset =
676 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
677 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
678 }
679}
680
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700681static inline bool free_entry(void *key __unused,
682 void *value, void *context __unused)
683{
684 free(value);
685 return true;
686}
687
688static inline void free_map(Hashmap *map)
689{
690 if (map) {
691 hashmapForEach(map, free_entry, (void *) NULL);
692 hashmapFree(map);
693 }
694}
695
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800696static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 audio_patch_handle_t patch_handle)
698{
699 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
700 return;
701
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700702 struct audio_patch_info *p_info =
703 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
704 if (p_info) {
705 ALOGV("%s: Remove patch %d", __func__, patch_handle);
706 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
707 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708 free(p_info);
709 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700710}
711
712static inline int io_streams_map_insert(struct audio_device *adev,
713 struct audio_stream *stream,
714 audio_io_handle_t handle,
715 audio_patch_handle_t patch_handle)
716{
717 struct audio_stream_info *s_info =
718 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
719
720 if (s_info == NULL) {
721 ALOGE("%s: Could not allocate stream info", __func__);
722 return -ENOMEM;
723 }
724 s_info->stream = stream;
725 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726
727 pthread_mutex_lock(&adev->lock);
728 struct audio_stream_info *stream_info =
729 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730 if (stream_info != NULL)
731 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800732 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700733 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 return 0;
735}
736
737static inline void io_streams_map_remove(struct audio_device *adev,
738 audio_io_handle_t handle)
739{
740 pthread_mutex_lock(&adev->lock);
741 struct audio_stream_info *s_info =
742 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700745 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800748done:
749 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 return;
751}
752
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 audio_patch_handle_t handle)
755{
756 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 p_info = (struct audio_patch_info *)
758 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700759 return p_info;
760}
761
vivek mehtaa76401a2015-04-24 14:12:15 -0700762__attribute__ ((visibility ("default")))
763bool audio_hw_send_gain_dep_calibration(int level) {
764 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700766
767 pthread_mutex_lock(&adev_init_lock);
768
769 if (adev != NULL && adev->platform != NULL) {
770 pthread_mutex_lock(&adev->lock);
771 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700772
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530773 // cache level info for any of the use case which
774 // was not started.
775 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700776
vivek mehtaa76401a2015-04-24 14:12:15 -0700777 pthread_mutex_unlock(&adev->lock);
778 } else {
779 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
780 }
781
782 pthread_mutex_unlock(&adev_init_lock);
783
784 return ret_val;
785}
786
Ashish Jain5106d362016-05-11 19:23:33 +0530787static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
788{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800789 bool gapless_enabled = false;
790 const char *mixer_ctl_name = "Compress Gapless Playback";
791 struct mixer_ctl *ctl;
792
793 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700794 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530795
796 /*Disable gapless if its AV playback*/
797 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800798
799 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
800 if (!ctl) {
801 ALOGE("%s: Could not get ctl for mixer cmd - %s",
802 __func__, mixer_ctl_name);
803 return -EINVAL;
804 }
805
806 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
807 ALOGE("%s: Could not set gapless mode %d",
808 __func__, gapless_enabled);
809 return -EINVAL;
810 }
811 return 0;
812}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700813
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700814__attribute__ ((visibility ("default")))
815int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
816 int table_size) {
817 int ret_val = 0;
818 ALOGV("%s: enter ... ", __func__);
819
820 pthread_mutex_lock(&adev_init_lock);
821 if (adev == NULL) {
822 ALOGW("%s: adev is NULL .... ", __func__);
823 goto done;
824 }
825
826 pthread_mutex_lock(&adev->lock);
827 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
828 pthread_mutex_unlock(&adev->lock);
829done:
830 pthread_mutex_unlock(&adev_init_lock);
831 ALOGV("%s: exit ... ", __func__);
832 return ret_val;
833}
834
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800835bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800836{
837 bool ret = false;
838 ALOGV("%s: enter ...", __func__);
839
840 pthread_mutex_lock(&adev_init_lock);
841
842 if (adev != NULL && adev->platform != NULL) {
843 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800844 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800845 pthread_mutex_unlock(&adev->lock);
846 }
847
848 pthread_mutex_unlock(&adev_init_lock);
849
850 ALOGV("%s: exit with ret %d", __func__, ret);
851 return ret;
852}
Aalique Grahame22e49102018-12-18 14:23:57 -0800853
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700854static bool is_supported_format(audio_format_t format)
855{
Eric Laurent86e17132013-09-12 17:49:30 -0700856 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530857 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530858 format == AUDIO_FORMAT_AAC_LC ||
859 format == AUDIO_FORMAT_AAC_HE_V1 ||
860 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530861 format == AUDIO_FORMAT_AAC_ADTS_LC ||
862 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
863 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530864 format == AUDIO_FORMAT_AAC_LATM_LC ||
865 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
866 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530867 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
868 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530869 format == AUDIO_FORMAT_PCM_FLOAT ||
870 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700871 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530872 format == AUDIO_FORMAT_AC3 ||
873 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700874 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530875 format == AUDIO_FORMAT_DTS ||
876 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800877 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530878 format == AUDIO_FORMAT_ALAC ||
879 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530880 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530881 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800882 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530883 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700884 format == AUDIO_FORMAT_APTX ||
885 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800886 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700887
888 return false;
889}
890
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700891static inline bool is_mmap_usecase(audio_usecase_t uc_id)
892{
893 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800894 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700895 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
896}
897
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700898static inline bool is_valid_volume(float left, float right)
899{
900 return ((left >= 0.0f && right >= 0.0f) ? true : false);
901}
902
Avinash Vaish71a8b972014-07-24 15:36:33 +0530903static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
904 struct audio_usecase *uc_info)
905{
906 struct listnode *node;
907 struct audio_usecase *usecase;
908
909 if (uc_info == NULL)
910 return -EINVAL;
911
912 /* Re-route all voice usecases on the shared backend other than the
913 specified usecase to new snd devices */
914 list_for_each(node, &adev->usecase_list) {
915 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800916 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530917 enable_audio_route(adev, usecase);
918 }
919 return 0;
920}
921
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530922static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530923{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530924 ALOGV("%s", __func__);
925 audio_route_apply_and_update_path(adev->audio_route,
926 "asrc-mode");
927 adev->asrc_mode_enabled = true;
928}
929
930static void disable_asrc_mode(struct audio_device *adev)
931{
932 ALOGV("%s", __func__);
933 audio_route_reset_and_update_path(adev->audio_route,
934 "asrc-mode");
935 adev->asrc_mode_enabled = false;
936}
937
938/*
939 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
940 * 44.1 or Native DSD backends are enabled for any of current use case.
941 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
942 * - Disable current mix path use case(Headphone backend) and re-enable it with
943 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
944 * e.g. Naitve DSD or Headphone 44.1 -> + 48
945 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530946static void check_and_set_asrc_mode(struct audio_device *adev,
947 struct audio_usecase *uc_info,
948 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530949{
950 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530951 int i, num_new_devices = 0;
952 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
953 /*
954 *Split snd device for new combo use case
955 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
956 */
957 if (platform_split_snd_device(adev->platform,
958 snd_device,
959 &num_new_devices,
960 split_new_snd_devices) == 0) {
961 for (i = 0; i < num_new_devices; i++)
962 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
963 } else {
964 int new_backend_idx = platform_get_backend_index(snd_device);
965 if (((new_backend_idx == HEADPHONE_BACKEND) ||
966 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
967 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
968 !adev->asrc_mode_enabled) {
969 struct listnode *node = NULL;
970 struct audio_usecase *uc = NULL;
971 struct stream_out *curr_out = NULL;
972 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
973 int i, num_devices, ret = 0;
974 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530975
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530976 list_for_each(node, &adev->usecase_list) {
977 uc = node_to_item(node, struct audio_usecase, list);
978 curr_out = (struct stream_out*) uc->stream.out;
979 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
980 /*
981 *Split snd device for existing combo use case
982 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
983 */
984 ret = platform_split_snd_device(adev->platform,
985 uc->out_snd_device,
986 &num_devices,
987 split_snd_devices);
988 if (ret < 0 || num_devices == 0) {
989 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
990 split_snd_devices[0] = uc->out_snd_device;
991 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800992 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530993 for (i = 0; i < num_devices; i++) {
994 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
995 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
996 if((new_backend_idx == HEADPHONE_BACKEND) &&
997 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
998 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700999 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301000 __func__);
1001 enable_asrc_mode(adev);
1002 break;
1003 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1004 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1005 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001006 ALOGV("%s: 48K stream detected, disabling and enabling it \
1007 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301008 disable_audio_route(adev, uc);
1009 disable_snd_device(adev, uc->out_snd_device);
1010 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1011 if (new_backend_idx == DSD_NATIVE_BACKEND)
1012 audio_route_apply_and_update_path(adev->audio_route,
1013 "hph-true-highquality-mode");
1014 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1015 (curr_out->bit_width >= 24))
1016 audio_route_apply_and_update_path(adev->audio_route,
1017 "hph-highquality-mode");
1018 enable_asrc_mode(adev);
1019 enable_snd_device(adev, uc->out_snd_device);
1020 enable_audio_route(adev, uc);
1021 break;
1022 }
1023 }
1024 // reset split devices count
1025 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001026 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301027 if (adev->asrc_mode_enabled)
1028 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301029 }
1030 }
1031 }
1032}
1033
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001034static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1035 struct audio_effect_config effect_config,
1036 unsigned int param_value)
1037{
1038 char mixer_ctl_name[] = "Audio Effect";
1039 struct mixer_ctl *ctl;
1040 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001041 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001042
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001043 if (in == NULL) {
1044 ALOGE("%s: active input stream is NULL", __func__);
1045 return -EINVAL;
1046 }
1047
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001048 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1049 if (!ctl) {
1050 ALOGE("%s: Could not get mixer ctl - %s",
1051 __func__, mixer_ctl_name);
1052 return -EINVAL;
1053 }
1054
1055 set_values[0] = 1; //0:Rx 1:Tx
1056 set_values[1] = in->app_type_cfg.app_type;
1057 set_values[2] = (long)effect_config.module_id;
1058 set_values[3] = (long)effect_config.instance_id;
1059 set_values[4] = (long)effect_config.param_id;
1060 set_values[5] = param_value;
1061
1062 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1063
1064 return 0;
1065
1066}
1067
1068static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1069 int effect_type, unsigned int *param_value)
1070{
1071 int ret = 0;
1072 struct audio_effect_config other_effect_config;
1073 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001074 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001075
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001076 if (in == NULL) {
1077 ALOGE("%s: active input stream is NULL", __func__);
1078 return -EINVAL;
1079 }
1080
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001081 usecase = get_usecase_from_list(adev, in->usecase);
1082 if (!usecase)
1083 return -EINVAL;
1084
1085 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1086 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1087 if (ret < 0) {
1088 ALOGE("%s Failed to get effect params %d", __func__, ret);
1089 return ret;
1090 }
1091
1092 if (module_id == other_effect_config.module_id) {
1093 //Same module id for AEC/NS. Values need to be combined
1094 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1095 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1096 *param_value |= other_effect_config.param_value;
1097 }
1098 }
1099
1100 return ret;
1101}
1102
1103static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301104{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001105 struct audio_effect_config effect_config;
1106 struct audio_usecase *usecase = NULL;
1107 int ret = 0;
1108 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001109 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001110
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001111 if(!voice_extn_is_dynamic_ecns_enabled())
1112 return ENOSYS;
1113
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001114 if (!in) {
1115 ALOGE("%s: Invalid input stream", __func__);
1116 return -EINVAL;
1117 }
1118
1119 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1120
1121 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001122 if (usecase == NULL) {
1123 ALOGE("%s: Could not find the usecase (%d) in the list",
1124 __func__, in->usecase);
1125 return -EINVAL;
1126 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001127
1128 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1129 if (ret < 0) {
1130 ALOGE("%s Failed to get module id %d", __func__, ret);
1131 return ret;
1132 }
1133 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1134 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1135
1136 if(enable)
1137 param_value = effect_config.param_value;
1138
1139 /*Special handling for AEC & NS effects Param values need to be
1140 updated if module ids are same*/
1141
1142 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1143 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1144 if (ret < 0)
1145 return ret;
1146 }
1147
1148 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1149
1150 return ret;
1151}
1152
1153static void check_and_enable_effect(struct audio_device *adev)
1154{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001155 if(!voice_extn_is_dynamic_ecns_enabled())
1156 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001157
Eric Laurent637e2d42018-11-15 12:24:31 -08001158 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001159
Eric Laurent637e2d42018-11-15 12:24:31 -08001160 if (in != NULL && !in->standby) {
1161 if (in->enable_aec)
1162 enable_disable_effect(adev, EFFECT_AEC, true);
1163
1164 if (in->enable_ns &&
1165 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1166 enable_disable_effect(adev, EFFECT_NS, true);
1167 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001168 }
1169}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001170
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001171int pcm_ioctl(struct pcm *pcm, int request, ...)
1172{
1173 va_list ap;
1174 void * arg;
1175 int pcm_fd = *(int*)pcm;
1176
1177 va_start(ap, request);
1178 arg = va_arg(ap, void *);
1179 va_end(ap);
1180
1181 return ioctl(pcm_fd, request, arg);
1182}
1183
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001184int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001185 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001188 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301189 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301190 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001191 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301192 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001193
1194 if (usecase == NULL)
1195 return -EINVAL;
1196
1197 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1198
Carter Hsu2e429db2019-05-14 18:50:52 +08001199 if (usecase->type == PCM_CAPTURE) {
1200 struct stream_in *in = usecase->stream.in;
1201 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001203
1204 if (in) {
1205 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206 list_init(&out_devices);
1207 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 struct listnode *node;
1209 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1210 USECASE_AUDIO_PLAYBACK_VOIP);
1211 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001212 assign_devices(&out_devices,
1213 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001214 } else if (adev->primary_output &&
1215 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216 assign_devices(&out_devices,
1217 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 } else {
1219 list_for_each(node, &adev->usecase_list) {
1220 uinfo = node_to_item(node, struct audio_usecase, list);
1221 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001222 assign_devices(&out_devices,
1223 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 break;
1225 }
1226 }
1227 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001228
1229 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001230 in->ec_opened = true;
1231 }
1232 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001233 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1234 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1235 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 snd_device = usecase->in_snd_device;
1237 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001239 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001240
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001241#ifdef DS1_DOLBY_DAP_ENABLED
1242 audio_extn_dolby_set_dmid(adev);
1243 audio_extn_dolby_set_endpoint(adev);
1244#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001245 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001246 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301247 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001248 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001249 if (audio_extn_is_maxx_audio_enabled())
1250 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301251 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301252 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1253 out = usecase->stream.out;
1254 if (out && out->compr)
1255 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1256 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301257
1258 if (usecase->type == PCM_CAPTURE) {
1259 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001260 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301261 ALOGD("%s: set custom mtmx params v1", __func__);
1262 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1263 }
1264 } else {
1265 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1266 }
Manish Dewangan58229382017-02-02 15:48:41 +05301267
Andy Hung756ecc12018-10-19 17:47:12 -07001268 // we shouldn't truncate mixer_path
1269 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1270 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1271 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001272 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001273 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301274 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1275 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1276 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1277 if (parms) {
1278 audio_extn_fm_set_parameters(adev, parms);
1279 str_parms_destroy(parms);
1280 }
1281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 ALOGV("%s: exit", __func__);
1283 return 0;
1284}
1285
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001286int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001287 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001290 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301291 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001292
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301293 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001294 return -EINVAL;
1295
1296 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301297 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 snd_device = usecase->in_snd_device;
1299 else
1300 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001301
1302 /* disable island and power mode on supported device for voice call */
1303 if (usecase->type == VOICE_CALL) {
1304 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1305 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1306 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1307 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1308 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1309 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001310 if (voice_is_lte_call_active(adev))
1311 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001312 ALOGD("%s: disable island cfg and power mode in voice tx path",
1313 __func__);
1314 }
1315 }
1316 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1317 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1318 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1319 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1320 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1321 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1322 ALOGD("%s: disable island cfg and power mode in voice rx path",
1323 __func__);
1324 }
1325 }
1326 }
1327
Andy Hung756ecc12018-10-19 17:47:12 -07001328 // we shouldn't truncate mixer_path
1329 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1330 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1331 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001332 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001333 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001334 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001335 if (usecase->type == PCM_CAPTURE) {
1336 struct stream_in *in = usecase->stream.in;
1337 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001338 struct listnode out_devices;
1339 list_init(&out_devices);
1340 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001341 in->ec_opened = false;
1342 }
1343 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001344 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301345 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301346
1347 if (usecase->type == PCM_CAPTURE) {
1348 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001349 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301350 ALOGD("%s: reset custom mtmx params v1", __func__);
1351 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1352 }
1353 } else {
1354 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1355 }
1356
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001357 if ((usecase->type == PCM_PLAYBACK) &&
1358 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301359 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361 ALOGV("%s: exit", __func__);
1362 return 0;
1363}
1364
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001365int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001366 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301368 int i, num_devices = 0;
1369 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1371
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001372 if (snd_device < SND_DEVICE_MIN ||
1373 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001374 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001375 return -EINVAL;
1376 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001378 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001379 ALOGE("%s: Invalid sound device returned", __func__);
1380 return -EINVAL;
1381 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001382
1383 adev->snd_dev_ref_cnt[snd_device]++;
1384
1385 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1386 (platform_split_snd_device(adev->platform,
1387 snd_device,
1388 &num_devices,
1389 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001390 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001391 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 return 0;
1393 }
1394
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001395 if (audio_extn_spkr_prot_is_enabled())
1396 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001397
Aalique Grahame22e49102018-12-18 14:23:57 -08001398 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1399
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001400 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1401 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001402 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1403 goto err;
1404 }
1405 audio_extn_dev_arbi_acquire(snd_device);
1406 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001407 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001408 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001409 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001410 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001411 } else if (platform_split_snd_device(adev->platform,
1412 snd_device,
1413 &num_devices,
1414 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301415 for (i = 0; i < num_devices; i++) {
1416 enable_snd_device(adev, new_snd_devices[i]);
1417 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001418 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001419 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001420 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301421
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001422 /* enable island and power mode on supported device */
1423 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1424 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1425 platform_set_island_cfg_on_device(adev, snd_device, true);
1426 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001427 if (voice_is_lte_call_active(adev) &&
1428 (snd_device >= SND_DEVICE_IN_BEGIN &&
1429 snd_device < SND_DEVICE_IN_END))
1430 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001431 ALOGD("%s: enable island cfg and power mode on: %s",
1432 __func__, device_name);
1433 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301434
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301435 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1436 if (audio_extn_a2dp_start_playback() < 0) {
1437 ALOGE(" fail to configure A2dp Source control path ");
1438 goto err;
1439 } else {
1440 adev->a2dp_started = true;
1441 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001442 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001443
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1445 (audio_extn_a2dp_start_capture() < 0)) {
1446 ALOGE(" fail to configure A2dp Sink control path ");
1447 goto err;
1448 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301449
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001450 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1451 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1452 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1453 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1454 ALOGE(" fail to configure sco control path ");
1455 goto err;
1456 }
Zhou Song12c29502019-03-16 10:37:18 +08001457 }
1458
Zhou Song331c8e52019-08-26 14:16:12 +08001459 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001460 /* due to the possibility of calibration overwrite between listen
1461 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001462 audio_extn_sound_trigger_update_device_status(snd_device,
1463 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301464 audio_extn_listen_update_device_status(snd_device,
1465 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001466 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001467 audio_extn_sound_trigger_update_device_status(snd_device,
1468 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301469 audio_extn_listen_update_device_status(snd_device,
1470 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001471 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001472 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001473 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001474 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301475
1476 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1477 !adev->native_playback_enabled &&
1478 audio_is_true_native_stream_active(adev)) {
1479 ALOGD("%s: %d: napb: enabling native mode in hardware",
1480 __func__, __LINE__);
1481 audio_route_apply_and_update_path(adev->audio_route,
1482 "true-native-mode");
1483 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301484 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301485 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1486 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001487 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001488 ALOGD("%s: init ec ref loopback", __func__);
1489 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001493err:
1494 adev->snd_dev_ref_cnt[snd_device]--;
1495 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496}
1497
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001498int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001499 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301501 int i, num_devices = 0;
1502 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001503 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1504
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001505 if (snd_device < SND_DEVICE_MIN ||
1506 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001507 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001508 return -EINVAL;
1509 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001510
1511 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1512 ALOGE("%s: Invalid sound device returned", __func__);
1513 return -EINVAL;
1514 }
1515
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1517 ALOGE("%s: device ref cnt is already 0", __func__);
1518 return -EINVAL;
1519 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001520
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001522
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001523
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001525 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301526
Aalique Grahame22e49102018-12-18 14:23:57 -08001527 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1528
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001529 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1530 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001531 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001532
1533 // when speaker device is disabled, reset swap.
1534 // will be renabled on usecase start
1535 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001536 } else if (platform_split_snd_device(adev->platform,
1537 snd_device,
1538 &num_devices,
1539 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301540 for (i = 0; i < num_devices; i++) {
1541 disable_snd_device(adev, new_snd_devices[i]);
1542 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001543 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001544 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001545 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001546 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001547
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301548 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301549 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301550 adev->a2dp_started = false;
1551 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001552 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001553 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001554 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301555 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001556 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301557 adev->native_playback_enabled) {
1558 ALOGD("%s: %d: napb: disabling native mode in hardware",
1559 __func__, __LINE__);
1560 audio_route_reset_and_update_path(adev->audio_route,
1561 "true-native-mode");
1562 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001563 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301564 adev->asrc_mode_enabled) {
1565 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301566 disable_asrc_mode(adev);
1567 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001568 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301569 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001570 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001571 ALOGD("%s: deinit ec ref loopback", __func__);
1572 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1573 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001574
1575 audio_extn_utils_release_snd_device(snd_device);
1576 } else {
1577 if (platform_split_snd_device(adev->platform,
1578 snd_device,
1579 &num_devices,
1580 new_snd_devices) == 0) {
1581 for (i = 0; i < num_devices; i++) {
1582 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1583 }
1584 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 return 0;
1588}
1589
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001590/*
1591 legend:
1592 uc - existing usecase
1593 new_uc - new usecase
1594 d1, d11, d2 - SND_DEVICE enums
1595 a1, a2 - corresponding ANDROID device enums
1596 B1, B2 - backend strings
1597
1598case 1
1599 uc->dev d1 (a1) B1
1600 new_uc->dev d1 (a1), d2 (a2) B1, B2
1601
1602 resolution: disable and enable uc->dev on d1
1603
1604case 2
1605 uc->dev d1 (a1) B1
1606 new_uc->dev d11 (a1) B1
1607
1608 resolution: need to switch uc since d1 and d11 are related
1609 (e.g. speaker and voice-speaker)
1610 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1611
1612case 3
1613 uc->dev d1 (a1) B1
1614 new_uc->dev d2 (a2) B2
1615
1616 resolution: no need to switch uc
1617
1618case 4
1619 uc->dev d1 (a1) B1
1620 new_uc->dev d2 (a2) B1
1621
1622 resolution: disable enable uc-dev on d2 since backends match
1623 we cannot enable two streams on two different devices if they
1624 share the same backend. e.g. if offload is on speaker device using
1625 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1626 using the same backend, offload must also be switched to voice-handset.
1627
1628case 5
1629 uc->dev d1 (a1) B1
1630 new_uc->dev d1 (a1), d2 (a2) B1
1631
1632 resolution: disable enable uc-dev on d2 since backends match
1633 we cannot enable two streams on two different devices if they
1634 share the same backend.
1635
1636case 6
1637 uc->dev d1 (a1) B1
1638 new_uc->dev d2 (a1) B2
1639
1640 resolution: no need to switch
1641
1642case 7
1643 uc->dev d1 (a1), d2 (a2) B1, B2
1644 new_uc->dev d1 (a1) B1
1645
1646 resolution: no need to switch
1647
Zhou Song4ba65882018-07-09 14:48:07 +08001648case 8
1649 uc->dev d1 (a1) B1
1650 new_uc->dev d11 (a1), d2 (a2) B1, B2
1651 resolution: compared to case 1, for this case, d1 and d11 are related
1652 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301653
1654case 9
1655 uc->dev d1 (a1), d2(a2) B1 B2
1656 new_uc->dev d1 (a1), d22 (a2) B1, B2
1657 resolution: disable enable uc-dev on d2 since backends match
1658 we cannot enable two streams on two different devices if they
1659 share the same backend. This is special case for combo use case
1660 with a2dp and sco devices which uses same backend.
1661 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001662*/
1663static snd_device_t derive_playback_snd_device(void * platform,
1664 struct audio_usecase *uc,
1665 struct audio_usecase *new_uc,
1666 snd_device_t new_snd_device)
1667{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001668 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001669
1670 snd_device_t d1 = uc->out_snd_device;
1671 snd_device_t d2 = new_snd_device;
1672
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001673 list_init(&a1);
1674 list_init(&a2);
1675
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301676 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301677 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1679 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301680 break;
1681 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001682 assign_devices(&a1, &uc->stream.out->device_list);
1683 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301684 break;
1685 }
1686
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001687 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001688 if (!compare_devices(&a1, &a2) &&
1689 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001690 snd_device_t d3[2];
1691 int num_devices = 0;
1692 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001693 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001694 &num_devices,
1695 d3);
1696 if (ret < 0) {
1697 if (ret != -ENOSYS) {
1698 ALOGW("%s failed to split snd_device %d",
1699 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001700 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701 }
1702 goto end;
1703 }
1704
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001705 if (platform_check_backends_match(d3[0], d3[1])) {
1706 return d2; // case 5
1707 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301708 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1709 platform_check_backends_match(d1, d2))
1710 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001711 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301712 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001713 // check if d1 is related to any of d3's
1714 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001715 return d1; // case 1
1716 else
1717 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001718 }
1719 } else {
1720 if (platform_check_backends_match(d1, d2)) {
1721 return d2; // case 2, 4
1722 } else {
1723 return d1; // case 6, 3
1724 }
1725 }
1726
1727end:
1728 return d2; // return whatever was calculated before.
1729}
1730
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001731static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301732 struct audio_usecase *uc_info,
1733 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001734{
1735 struct listnode *node;
1736 struct audio_usecase *usecase;
1737 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301738 snd_device_t uc_derive_snd_device;
1739 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001740 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1741 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001742 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301743 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001744 /*
1745 * This function is to make sure that all the usecases that are active on
1746 * the hardware codec backend are always routed to any one device that is
1747 * handled by the hardware codec.
1748 * For example, if low-latency and deep-buffer usecases are currently active
1749 * on speaker and out_set_parameters(headset) is received on low-latency
1750 * output, then we have to make sure deep-buffer is also switched to headset,
1751 * because of the limitation that both the devices cannot be enabled
1752 * at the same time as they share the same backend.
1753 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001754 /*
1755 * This call is to check if we need to force routing for a particular stream
1756 * If there is a backend configuration change for the device when a
1757 * new stream starts, then ADM needs to be closed and re-opened with the new
1758 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001759 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001760 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001761 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1762 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301763 /* For a2dp device reconfigure all active sessions
1764 * with new AFE encoder format based on a2dp state
1765 */
1766 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301767 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1768 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301769 audio_extn_a2dp_is_force_device_switch()) {
1770 force_routing = true;
1771 force_restart_session = true;
1772 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001773
1774 /*
1775 * Island cfg and power mode config needs to set before AFE port start.
1776 * Set force routing in case of voice device was enable before.
1777 */
1778 if (uc_info->type == VOICE_CALL &&
1779 voice_extn_is_voice_power_mode_supported() &&
1780 platform_check_and_update_island_power_status(adev->platform,
1781 uc_info,
1782 snd_device)) {
1783 force_routing = true;
1784 ALOGD("%s:becf: force routing %d for power mode supported device",
1785 __func__, force_routing);
1786 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301787 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1788
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001790 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001791 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001792 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1793 switch_device[i] = false;
1794
1795 list_for_each(node, &adev->usecase_list) {
1796 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001797
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301798 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1799 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301800 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301801 platform_get_snd_device_name(usecase->out_snd_device),
1802 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301803 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1804 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301805 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1806 usecase, uc_info, snd_device);
1807 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001808 (is_codec_backend_out_device_type(&usecase->device_list) ||
1809 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1810 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1811 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1812 is_a2dp_out_device_type(&usecase->device_list) ||
1813 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301814 ((force_restart_session) ||
1815 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301816 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1817 __func__, use_case_table[usecase->id],
1818 platform_get_snd_device_name(usecase->out_snd_device));
1819 disable_audio_route(adev, usecase);
1820 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301821 /* Enable existing usecase on derived playback device */
1822 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301823 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 }
1826 }
1827
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301828 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1829 num_uc_to_switch);
1830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001832 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001833
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301834 /* Make sure the previous devices to be disabled first and then enable the
1835 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 list_for_each(node, &adev->usecase_list) {
1837 usecase = node_to_item(node, struct audio_usecase, list);
1838 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001839 /* Check if output sound device to be switched can be split and if any
1840 of the split devices match with derived sound device */
1841 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1842 &num_devices, split_snd_devices) == 0) {
1843 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1844 for (i = 0; i < num_devices; i++) {
1845 /* Disable devices that do not match with derived sound device */
1846 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1847 disable_snd_device(adev, split_snd_devices[i]);
1848 }
1849 } else {
1850 disable_snd_device(adev, usecase->out_snd_device);
1851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 }
1853 }
1854
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001855 list_for_each(node, &adev->usecase_list) {
1856 usecase = node_to_item(node, struct audio_usecase, list);
1857 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001858 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1859 &num_devices, split_snd_devices) == 0) {
1860 /* Enable derived sound device only if it does not match with
1861 one of the split sound devices. This is because the matching
1862 sound device was not disabled */
1863 bool should_enable = true;
1864 for (i = 0; i < num_devices; i++) {
1865 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1866 should_enable = false;
1867 break;
1868 }
1869 }
1870 if (should_enable)
1871 enable_snd_device(adev, derive_snd_device[usecase->id]);
1872 } else {
1873 enable_snd_device(adev, derive_snd_device[usecase->id]);
1874 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001875 }
1876 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 /* Re-route all the usecases on the shared backend other than the
1879 specified usecase to new snd devices */
1880 list_for_each(node, &adev->usecase_list) {
1881 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301882 /* Update the out_snd_device only before enabling the audio route */
1883 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301884 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301885 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301886 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301887 use_case_table[usecase->id],
1888 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001889 /* Update voc calibration before enabling VoIP route */
1890 if (usecase->type == VOIP_CALL)
1891 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001892 usecase->out_snd_device,
1893 platform_get_input_snd_device(
1894 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301895 &uc_info->device_list,
1896 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301897 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301898 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001899 out_set_voip_volume(&usecase->stream.out->stream,
1900 usecase->stream.out->volume_l,
1901 usecase->stream.out->volume_r);
1902 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301903 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 }
1905 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001906 }
1907}
1908
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301909static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001910 struct audio_usecase *uc_info,
1911 snd_device_t snd_device)
1912{
1913 struct listnode *node;
1914 struct audio_usecase *usecase;
1915 bool switch_device[AUDIO_USECASE_MAX];
1916 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001917 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001918 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001919
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301920 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1921 snd_device);
1922 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301923
1924 /*
1925 * Make sure out devices is checked against out codec backend device and
1926 * also in devices against in codec backend. Checking out device against in
1927 * codec backend or vice versa causes issues.
1928 */
1929 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001930 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001931
1932 /*
1933 * Island cfg and power mode config needs to set before AFE port start.
1934 * Set force routing in case of voice device was enable before.
1935 */
1936
1937 if (uc_info->type == VOICE_CALL &&
1938 voice_extn_is_voice_power_mode_supported() &&
1939 platform_check_and_update_island_power_status(adev->platform,
1940 uc_info,
1941 snd_device)) {
1942 force_routing = true;
1943 ALOGD("%s:becf: force routing %d for power mode supported device",
1944 __func__, force_routing);
1945 }
1946
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001947 /*
1948 * This function is to make sure that all the active capture usecases
1949 * are always routed to the same input sound device.
1950 * For example, if audio-record and voice-call usecases are currently
1951 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1952 * is received for voice call then we have to make sure that audio-record
1953 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1954 * because of the limitation that two devices cannot be enabled
1955 * at the same time if they share the same backend.
1956 */
1957 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1958 switch_device[i] = false;
1959
1960 list_for_each(node, &adev->usecase_list) {
1961 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301962 /*
1963 * TODO: Enhance below condition to handle BT sco/USB multi recording
1964 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301965
1966 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1967 (usecase->in_snd_device != snd_device || force_routing));
1968 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1969 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1970 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001971 ((backend_check_cond &&
1972 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001973 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001974 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001975 is_single_device_type_equal(&usecase->device_list,
1976 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001977 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001978 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001979 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301980 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001981 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001982 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001983 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001984 switch_device[usecase->id] = true;
1985 num_uc_to_switch++;
1986 }
1987 }
1988
1989 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001990 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001991
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301992 /* Make sure the previous devices to be disabled first and then enable the
1993 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001994 list_for_each(node, &adev->usecase_list) {
1995 usecase = node_to_item(node, struct audio_usecase, list);
1996 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001997 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001998 }
1999 }
2000
2001 list_for_each(node, &adev->usecase_list) {
2002 usecase = node_to_item(node, struct audio_usecase, list);
2003 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002004 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002005 }
2006 }
2007
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002008 /* Re-route all the usecases on the shared backend other than the
2009 specified usecase to new snd devices */
2010 list_for_each(node, &adev->usecase_list) {
2011 usecase = node_to_item(node, struct audio_usecase, list);
2012 /* Update the in_snd_device only before enabling the audio route */
2013 if (switch_device[usecase->id] ) {
2014 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002015 if (usecase->type != VOICE_CALL) {
2016 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302017 if (usecase->type == VOIP_CALL) {
2018 snd_device_t voip_snd_device;
2019 voip_snd_device = platform_get_output_snd_device(adev->platform,
2020 uc_info->stream.out,
2021 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002022 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302023 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002024 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302025 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302026 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002027 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002028 }
2029 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002030 }
2031}
2032
Mingming Yin3a941d42016-02-17 18:08:05 -08002033static void reset_hdmi_sink_caps(struct stream_out *out) {
2034 int i = 0;
2035
2036 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2037 out->supported_channel_masks[i] = 0;
2038 }
2039 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2040 out->supported_formats[i] = 0;
2041 }
2042 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2043 out->supported_sample_rates[i] = 0;
2044 }
2045}
2046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002048static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049{
Mingming Yin3a941d42016-02-17 18:08:05 -08002050 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002051 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2052 out->extconn.cs.controller,
2053 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054
Mingming Yin3a941d42016-02-17 18:08:05 -08002055 reset_hdmi_sink_caps(out);
2056
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002057 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002058 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002059 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002060 out->extconn.cs.stream);
2061 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002062 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002063 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002064 }
2065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002068 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002069 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002070 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2071 case 6:
2072 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2073 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2074 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2075 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2076 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2077 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 break;
2079 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002080 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002081 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 break;
2083 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002084
2085 // check channel format caps
2086 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002087 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2088 out->extconn.cs.controller,
2089 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002090 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2091 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2092 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2093 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2094 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2095 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2096 }
2097
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002098 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2099 out->extconn.cs.controller,
2100 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002101 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2102 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2103 }
2104
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002105 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2106 out->extconn.cs.controller,
2107 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002108 ALOGV(":%s HDMI supports DTS format", __func__);
2109 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2110 }
2111
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002112 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2113 out->extconn.cs.controller,
2114 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002115 ALOGV(":%s HDMI supports DTS HD format", __func__);
2116 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2117 }
2118
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002119 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2120 out->extconn.cs.controller,
2121 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002122 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2123 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2124 }
2125
Mingming Yin3a941d42016-02-17 18:08:05 -08002126
2127 // check sample rate caps
2128 i = 0;
2129 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002130 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2131 out->extconn.cs.controller,
2132 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002133 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2134 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2135 }
2136 }
2137
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002138 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139}
2140
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002141static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2142 uint32_t *supported_sample_rates __unused,
2143 uint32_t max_rates __unused)
2144{
2145 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2146 supported_sample_rates,
2147 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302148 ssize_t i = 0;
2149
2150 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002151 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2152 supported_sample_rates[i]);
2153 }
2154 return count;
2155}
2156
2157static inline int read_usb_sup_channel_masks(bool is_playback,
2158 audio_channel_mask_t *supported_channel_masks,
2159 uint32_t max_masks)
2160{
2161 int channels = audio_extn_usb_get_max_channels(is_playback);
2162 int channel_count;
2163 uint32_t num_masks = 0;
2164 if (channels > MAX_HIFI_CHANNEL_COUNT)
2165 channels = MAX_HIFI_CHANNEL_COUNT;
2166
2167 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002168 // start from 2 channels as framework currently doesn't support mono.
2169 if (channels >= FCC_2) {
2170 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2171 }
2172 for (channel_count = FCC_2;
2173 channel_count <= channels && num_masks < max_masks;
2174 ++channel_count) {
2175 supported_channel_masks[num_masks++] =
2176 audio_channel_mask_for_index_assignment_from_count(channel_count);
2177 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002178 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002179 // For capture we report all supported channel masks from 1 channel up.
2180 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002181 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2182 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002183 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2184 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2185 if (channel_count <= FCC_2) {
2186 mask = audio_channel_in_mask_from_count(channel_count);
2187 supported_channel_masks[num_masks++] = mask;
2188 }
2189 const audio_channel_mask_t index_mask =
2190 audio_channel_mask_for_index_assignment_from_count(channel_count);
2191 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2192 supported_channel_masks[num_masks++] = index_mask;
2193 }
2194 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002195 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302196
vincenttewf51c94e2019-05-07 10:28:53 +08002197 for (size_t i = 0; i < num_masks; ++i) {
2198 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2199 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302200 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002201 return num_masks;
2202}
2203
2204static inline int read_usb_sup_formats(bool is_playback __unused,
2205 audio_format_t *supported_formats,
2206 uint32_t max_formats __unused)
2207{
2208 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2209 switch (bitwidth) {
2210 case 24:
2211 // XXX : usb.c returns 24 for s24 and s24_le?
2212 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2213 break;
2214 case 32:
2215 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2216 break;
2217 case 16:
2218 default :
2219 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2220 break;
2221 }
2222 ALOGV("%s: %s supported format %d", __func__,
2223 is_playback ? "P" : "C", bitwidth);
2224 return 1;
2225}
2226
2227static inline int read_usb_sup_params_and_compare(bool is_playback,
2228 audio_format_t *format,
2229 audio_format_t *supported_formats,
2230 uint32_t max_formats,
2231 audio_channel_mask_t *mask,
2232 audio_channel_mask_t *supported_channel_masks,
2233 uint32_t max_masks,
2234 uint32_t *rate,
2235 uint32_t *supported_sample_rates,
2236 uint32_t max_rates) {
2237 int ret = 0;
2238 int num_formats;
2239 int num_masks;
2240 int num_rates;
2241 int i;
2242
2243 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2244 max_formats);
2245 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2246 max_masks);
2247
2248 num_rates = read_usb_sup_sample_rates(is_playback,
2249 supported_sample_rates, max_rates);
2250
2251#define LUT(table, len, what, dflt) \
2252 for (i=0; i<len && (table[i] != what); i++); \
2253 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2254
2255 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2256 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2257 LUT(supported_sample_rates, num_rates, *rate, 0);
2258
2259#undef LUT
2260 return ret < 0 ? -EINVAL : 0; // HACK TBD
2261}
2262
Alexy Josephb1379942016-01-29 15:49:38 -08002263audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002264 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002265{
2266 struct audio_usecase *usecase;
2267 struct listnode *node;
2268
2269 list_for_each(node, &adev->usecase_list) {
2270 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002271 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002272 ALOGV("%s: usecase id %d", __func__, usecase->id);
2273 return usecase->id;
2274 }
2275 }
2276 return USECASE_INVALID;
2277}
2278
Alexy Josephb1379942016-01-29 15:49:38 -08002279struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002280 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281{
2282 struct audio_usecase *usecase;
2283 struct listnode *node;
2284
2285 list_for_each(node, &adev->usecase_list) {
2286 usecase = node_to_item(node, struct audio_usecase, list);
2287 if (usecase->id == uc_id)
2288 return usecase;
2289 }
2290 return NULL;
2291}
2292
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302293/*
2294 * is a true native playback active
2295 */
2296bool audio_is_true_native_stream_active(struct audio_device *adev)
2297{
2298 bool active = false;
2299 int i = 0;
2300 struct listnode *node;
2301
2302 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2303 ALOGV("%s:napb: not in true mode or non hdphones device",
2304 __func__);
2305 active = false;
2306 goto exit;
2307 }
2308
2309 list_for_each(node, &adev->usecase_list) {
2310 struct audio_usecase *uc;
2311 uc = node_to_item(node, struct audio_usecase, list);
2312 struct stream_out *curr_out =
2313 (struct stream_out*) uc->stream.out;
2314
2315 if (curr_out && PCM_PLAYBACK == uc->type) {
2316 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2317 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2318 uc->id, curr_out->sample_rate,
2319 curr_out->bit_width,
2320 platform_get_snd_device_name(uc->out_snd_device));
2321
2322 if (is_offload_usecase(uc->id) &&
2323 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2324 active = true;
2325 ALOGD("%s:napb:native stream detected", __func__);
2326 }
2327 }
2328 }
2329exit:
2330 return active;
2331}
2332
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002333uint32_t adev_get_dsp_bit_width_enforce_mode()
2334{
2335 if (adev == NULL) {
2336 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2337 return 0;
2338 }
2339 return adev->dsp_bit_width_enforce_mode;
2340}
2341
2342static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2343{
2344 char value[PROPERTY_VALUE_MAX];
2345 int trial;
2346 uint32_t dsp_bit_width_enforce_mode = 0;
2347
2348 if (!mixer) {
2349 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2350 __func__);
2351 return 0;
2352 }
2353
2354 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2355 value, NULL) > 0) {
2356 trial = atoi(value);
2357 switch (trial) {
2358 case 16:
2359 dsp_bit_width_enforce_mode = 16;
2360 break;
2361 case 24:
2362 dsp_bit_width_enforce_mode = 24;
2363 break;
2364 case 32:
2365 dsp_bit_width_enforce_mode = 32;
2366 break;
2367 default:
2368 dsp_bit_width_enforce_mode = 0;
2369 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2370 break;
2371 }
2372 }
2373
2374 return dsp_bit_width_enforce_mode;
2375}
2376
2377static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2378 uint32_t enforce_mode,
2379 bool enable)
2380{
2381 struct mixer_ctl *ctl = NULL;
2382 const char *mixer_ctl_name = "ASM Bit Width";
2383 uint32_t asm_bit_width_mode = 0;
2384
2385 if (enforce_mode == 0) {
2386 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2387 return;
2388 }
2389
2390 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2391 if (!ctl) {
2392 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2393 __func__, mixer_ctl_name);
2394 return;
2395 }
2396
2397 if (enable)
2398 asm_bit_width_mode = enforce_mode;
2399 else
2400 asm_bit_width_mode = 0;
2401
2402 ALOGV("%s DSP bit width feature status is %d width=%d",
2403 __func__, enable, asm_bit_width_mode);
2404 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2405 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2406 asm_bit_width_mode);
2407
2408 return;
2409}
2410
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302411/*
2412 * if native DSD playback active
2413 */
2414bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2415{
2416 bool active = false;
2417 struct listnode *node = NULL;
2418 struct audio_usecase *uc = NULL;
2419 struct stream_out *curr_out = NULL;
2420
2421 list_for_each(node, &adev->usecase_list) {
2422 uc = node_to_item(node, struct audio_usecase, list);
2423 curr_out = (struct stream_out*) uc->stream.out;
2424
2425 if (curr_out && PCM_PLAYBACK == uc->type &&
2426 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2427 active = true;
2428 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302429 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302430 }
2431 }
2432 return active;
2433}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302434
2435static bool force_device_switch(struct audio_usecase *usecase)
2436{
2437 bool ret = false;
2438 bool is_it_true_mode = false;
2439
Zhou Song30f2c3e2018-02-08 14:02:15 +08002440 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302441 usecase->type == TRANSCODE_LOOPBACK_RX ||
2442 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002443 return false;
2444 }
2445
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002446 if(usecase->stream.out == NULL) {
2447 ALOGE("%s: stream.out is NULL", __func__);
2448 return false;
2449 }
2450
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302451 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002452 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002453 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2454 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302455 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2456 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2457 (!is_it_true_mode && adev->native_playback_enabled)){
2458 ret = true;
2459 ALOGD("napb: time to toggle native mode");
2460 }
2461 }
2462
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302463 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302464 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2465 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002466 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302467 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302468 ALOGD("Force a2dp device switch to update new encoder config");
2469 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002470 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302471
Florian Pfister1a84f312018-07-19 14:38:18 +02002472 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302473 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2474 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002475 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302476 return ret;
2477}
2478
Aalique Grahame22e49102018-12-18 14:23:57 -08002479static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2480{
2481 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2482}
2483
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302484bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2485{
2486 bool ret=false;
2487 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002488 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2489 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302490 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2491 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002492 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302493 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002494 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2495 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302496 ret = true;
2497
2498 return ret;
2499}
2500
2501bool is_a2dp_device(snd_device_t out_snd_device)
2502{
2503 bool ret=false;
2504 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2505 ret = true;
2506
2507 return ret;
2508}
2509
2510bool is_bt_soc_on(struct audio_device *adev)
2511{
2512 struct mixer_ctl *ctl;
2513 char *mixer_ctl_name = "BT SOC status";
2514 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2515 bool bt_soc_status = true;
2516 if (!ctl) {
2517 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2518 __func__, mixer_ctl_name);
2519 /*This is to ensure we dont break targets which dont have the kernel change*/
2520 return true;
2521 }
2522 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2523 ALOGD("BT SOC status: %d",bt_soc_status);
2524 return bt_soc_status;
2525}
2526
Zhou Song331c8e52019-08-26 14:16:12 +08002527static int configure_btsco_sample_rate(snd_device_t snd_device)
2528{
2529 struct mixer_ctl *ctl = NULL;
2530 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2531 char *rate_str = NULL;
2532 bool is_rx_dev = true;
2533
2534 if (is_btsco_device(snd_device, snd_device)) {
2535 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2536 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2537 if (!ctl_sr_tx || !ctl_sr_rx) {
2538 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2539 if (!ctl_sr)
2540 return -ENOSYS;
2541 }
2542
2543 switch (snd_device) {
2544 case SND_DEVICE_OUT_BT_SCO:
2545 rate_str = "KHZ_8";
2546 break;
2547 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2548 case SND_DEVICE_IN_BT_SCO_MIC:
2549 rate_str = "KHZ_8";
2550 is_rx_dev = false;
2551 break;
2552 case SND_DEVICE_OUT_BT_SCO_WB:
2553 rate_str = "KHZ_16";
2554 break;
2555 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2556 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2557 rate_str = "KHZ_16";
2558 is_rx_dev = false;
2559 break;
2560 default:
2561 return 0;
2562 }
2563
2564 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2565 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2566 return -ENOSYS;
2567 }
2568 return 0;
2569}
2570
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302571int out_standby_l(struct audio_stream *stream);
2572
Eric Laurent637e2d42018-11-15 12:24:31 -08002573struct stream_in *adev_get_active_input(const struct audio_device *adev)
2574{
2575 struct listnode *node;
2576 struct stream_in *last_active_in = NULL;
2577
2578 /* Get last added active input.
2579 * TODO: We may use a priority mechanism to pick highest priority active source */
2580 list_for_each(node, &adev->usecase_list)
2581 {
2582 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2583 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2584 last_active_in = usecase->stream.in;
2585 }
2586
2587 return last_active_in;
2588}
2589
2590struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2591{
2592 struct listnode *node;
2593
2594 /* First check active inputs with voice communication source and then
2595 * any input if audio mode is in communication */
2596 list_for_each(node, &adev->usecase_list)
2597 {
2598 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2599 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2600 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2601 return usecase->stream.in;
2602 }
2603 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2604 return adev_get_active_input(adev);
2605
2606 return NULL;
2607}
2608
Carter Hsu2e429db2019-05-14 18:50:52 +08002609/*
2610 * Aligned with policy.h
2611 */
2612static inline int source_priority(int inputSource)
2613{
2614 switch (inputSource) {
2615 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2616 return 9;
2617 case AUDIO_SOURCE_CAMCORDER:
2618 return 8;
2619 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2620 return 7;
2621 case AUDIO_SOURCE_UNPROCESSED:
2622 return 6;
2623 case AUDIO_SOURCE_MIC:
2624 return 5;
2625 case AUDIO_SOURCE_ECHO_REFERENCE:
2626 return 4;
2627 case AUDIO_SOURCE_FM_TUNER:
2628 return 3;
2629 case AUDIO_SOURCE_VOICE_RECOGNITION:
2630 return 2;
2631 case AUDIO_SOURCE_HOTWORD:
2632 return 1;
2633 default:
2634 break;
2635 }
2636 return 0;
2637}
2638
2639static struct stream_in *get_priority_input(struct audio_device *adev)
2640{
2641 struct listnode *node;
2642 struct audio_usecase *usecase;
2643 int last_priority = 0, priority;
2644 struct stream_in *priority_in = NULL;
2645 struct stream_in *in;
2646
2647 list_for_each(node, &adev->usecase_list) {
2648 usecase = node_to_item(node, struct audio_usecase, list);
2649 if (usecase->type == PCM_CAPTURE) {
2650 in = usecase->stream.in;
2651 if (!in)
2652 continue;
2653 priority = source_priority(in->source);
2654
2655 if (priority > last_priority) {
2656 last_priority = priority;
2657 priority_in = in;
2658 }
2659 }
2660 }
2661 return priority_in;
2662}
2663
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002664int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002666 snd_device_t out_snd_device = SND_DEVICE_NONE;
2667 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002668 struct audio_usecase *usecase = NULL;
2669 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002670 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002671 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302672 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002673 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002674 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302676 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2677
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002678 usecase = get_usecase_from_list(adev, uc_id);
2679 if (usecase == NULL) {
2680 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2681 return -EINVAL;
2682 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002684 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002685 (usecase->type == VOIP_CALL) ||
2686 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302687 if(usecase->stream.out == NULL) {
2688 ALOGE("%s: stream.out is NULL", __func__);
2689 return -EINVAL;
2690 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002691 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002692 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2693 uc_id);
2694 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2695 uc_id);
2696 } else {
2697 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302698 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002699 in_snd_device = platform_get_input_snd_device(adev->platform,
2700 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302701 &usecase->stream.out->device_list,
2702 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002703 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002704 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302705 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302706 if (usecase->stream.inout == NULL) {
2707 ALOGE("%s: stream.inout is NULL", __func__);
2708 return -EINVAL;
2709 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002710 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302711 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2712 stream_out.format = usecase->stream.inout->out_config.format;
2713 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302714 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002715 assign_devices(&usecase->device_list,
2716 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302717 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2718 if (usecase->stream.inout == NULL) {
2719 ALOGE("%s: stream.inout is NULL", __func__);
2720 return -EINVAL;
2721 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302722 struct listnode out_devices;
2723 list_init(&out_devices);
2724 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2725 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002726 assign_devices(&usecase->device_list,
2727 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002728 } else {
2729 /*
2730 * If the voice call is active, use the sound devices of voice call usecase
2731 * so that it would not result any device switch. All the usecases will
2732 * be switched to new device when select_devices() is called for voice call
2733 * usecase. This is to avoid switching devices for voice call when
2734 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002735 * choose voice call device only if the use case device is
2736 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002738 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002739 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002740 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002741 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2742 is_codec_backend_out_device_type(&usecase->device_list)) ||
2743 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2744 is_codec_backend_in_device_type(&usecase->device_list)) ||
2745 is_single_device_type_equal(&vc_usecase->device_list,
2746 AUDIO_DEVICE_OUT_HEARING_AID) ||
2747 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002748 AUDIO_DEVICE_IN_VOICE_CALL) ||
2749 (is_single_device_type_equal(&usecase->device_list,
2750 AUDIO_DEVICE_IN_USB_HEADSET) &&
2751 is_single_device_type_equal(&vc_usecase->device_list,
2752 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002753 in_snd_device = vc_usecase->in_snd_device;
2754 out_snd_device = vc_usecase->out_snd_device;
2755 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002756 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002757 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002758 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002759 if ((voip_usecase != NULL) &&
2760 (usecase->type == PCM_PLAYBACK) &&
2761 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002762 out_snd_device_backend_match = platform_check_backends_match(
2763 voip_usecase->out_snd_device,
2764 platform_get_output_snd_device(
2765 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302766 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002767 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002768 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2769 (is_codec_backend_out_device_type(&usecase->device_list) ||
2770 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002771 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002772 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002773 in_snd_device = voip_usecase->in_snd_device;
2774 out_snd_device = voip_usecase->out_snd_device;
2775 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002776 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002777 hfp_ucid = audio_extn_hfp_get_usecase();
2778 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002779 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002780 in_snd_device = hfp_usecase->in_snd_device;
2781 out_snd_device = hfp_usecase->out_snd_device;
2782 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002783 }
2784 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302785 if (usecase->stream.out == NULL) {
2786 ALOGE("%s: stream.out is NULL", __func__);
2787 return -EINVAL;
2788 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002789 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002790 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002791 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002792 struct stream_out *voip_out = adev->primary_output;
2793 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002794 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002795 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2796 else
2797 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302798 usecase->stream.out,
2799 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002800 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002801
Eric Laurent637e2d42018-11-15 12:24:31 -08002802 if (voip_usecase)
2803 voip_out = voip_usecase->stream.out;
2804
2805 if (usecase->stream.out == voip_out && voip_in != NULL)
2806 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002807 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002808 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302809 if (usecase->stream.in == NULL) {
2810 ALOGE("%s: stream.in is NULL", __func__);
2811 return -EINVAL;
2812 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002813 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002814 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002815 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002816 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002817 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002818 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002819
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002820 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002821 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002822 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2823 USECASE_AUDIO_PLAYBACK_VOIP);
2824
Carter Hsu2e429db2019-05-14 18:50:52 +08002825 usecase->stream.in->enable_ec_port = false;
2826
Zhou Song62ea0282020-03-22 19:53:01 +08002827 bool is_ha_usecase = adev->ha_proxy_enable ?
2828 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2829 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2830 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002831 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002832 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002833 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002834 } else if (adev->primary_output &&
2835 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002836 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002837 } else {
2838 /* forcing speaker o/p device to get matching i/p pair
2839 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002840 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002841 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002842 priority_in = voip_in;
2843 } else {
2844 /* get the input with the highest priority source*/
2845 priority_in = get_priority_input(adev);
2846
2847 if (!priority_in)
2848 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002849 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002850
Eric Laurent637e2d42018-11-15 12:24:31 -08002851 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002852 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302853 &out_devices,
2854 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002855 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002856 }
2857 }
2858
2859 if (out_snd_device == usecase->out_snd_device &&
2860 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302861
2862 if (!force_device_switch(usecase))
2863 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864 }
2865
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002866 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002867 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002868 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002869 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2870 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302871 }
2872
Aalique Grahame22e49102018-12-18 14:23:57 -08002873 if (out_snd_device != SND_DEVICE_NONE &&
2874 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2875 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2876 __func__,
2877 use_case_table[uc_id],
2878 adev->last_logged_snd_device[uc_id][0],
2879 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2880 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2881 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2882 -1,
2883 out_snd_device,
2884 platform_get_snd_device_name(out_snd_device),
2885 platform_get_snd_device_acdb_id(out_snd_device));
2886 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2887 }
2888 if (in_snd_device != SND_DEVICE_NONE &&
2889 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2890 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2891 __func__,
2892 use_case_table[uc_id],
2893 adev->last_logged_snd_device[uc_id][1],
2894 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2895 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2896 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2897 -1,
2898 in_snd_device,
2899 platform_get_snd_device_name(in_snd_device),
2900 platform_get_snd_device_acdb_id(in_snd_device));
2901 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2902 }
2903
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 /*
2906 * Limitation: While in call, to do a device switch we need to disable
2907 * and enable both RX and TX devices though one of them is same as current
2908 * device.
2909 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002910 if ((usecase->type == VOICE_CALL) &&
2911 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2912 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002913 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002914 }
2915
2916 if (((usecase->type == VOICE_CALL) ||
2917 (usecase->type == VOIP_CALL)) &&
2918 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2919 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302920 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002921 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002922 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002923
2924 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302925 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002926 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002927 }
2928
Aalique Grahame22e49102018-12-18 14:23:57 -08002929 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2930 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002931 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302932 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002933 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2934 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2935 else
2936 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302937 }
2938
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002939 /* Disable current sound devices */
2940 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002941 disable_audio_route(adev, usecase);
2942 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 }
2944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002945 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002946 disable_audio_route(adev, usecase);
2947 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 }
2949
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002950 /* Applicable only on the targets that has external modem.
2951 * New device information should be sent to modem before enabling
2952 * the devices to reduce in-call device switch time.
2953 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002954 if ((usecase->type == VOICE_CALL) &&
2955 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2956 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002957 status = platform_switch_voice_call_enable_device_config(adev->platform,
2958 out_snd_device,
2959 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002960 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002961
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002962 /* Enable new sound devices */
2963 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002964 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302965 if (platform_check_codec_asrc_support(adev->platform))
2966 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002967 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08002968 /* Enable haptics device for haptic usecase */
2969 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
2970 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 }
2972
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002973 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302974 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002975 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002976 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002977
Avinash Vaish71a8b972014-07-24 15:36:33 +05302978 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002979 status = platform_switch_voice_call_device_post(adev->platform,
2980 out_snd_device,
2981 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302982 enable_audio_route_for_voice_usecases(adev, usecase);
2983 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002984
sangwoo170731f2013-06-08 15:36:36 +09002985 usecase->in_snd_device = in_snd_device;
2986 usecase->out_snd_device = out_snd_device;
2987
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302988 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2989 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302990 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002991 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002992 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002993 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2994 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2995 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2996 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2997 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2998 /*
2999 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3000 * configured device sample rate, if not update the COPP rate to be equal to the
3001 * device sample rate, else open COPP at stream sample rate
3002 */
3003 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3004 usecase->stream.out->sample_rate,
3005 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303006 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303007 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3008 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303009 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003010 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3011 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3012 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3013 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003014 }
3015 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003016
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003017 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003018
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003019 /* If input stream is already running then effect needs to be
3020 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003021 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003022 check_and_enable_effect(adev);
3023
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003024 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003025 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303026 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003027 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3028
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003029 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303030 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003031 voice_extn_compress_voip_is_started(adev))
3032 voice_set_sidetone(adev, out_snd_device, true);
3033 }
3034
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003035 /* Applicable only on the targets that has external modem.
3036 * Enable device command should be sent to modem only after
3037 * enabling voice call mixer controls
3038 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003039 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003040 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3041 out_snd_device,
3042 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303043
3044 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003045 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303046 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003047 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303048 if (is_bt_soc_on(adev) == false){
3049 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003050 if (in->pcm != NULL)
3051 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303052 }
3053 }
3054 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3055 && usecase->stream.out->started) {
3056 if (is_bt_soc_on(adev) == false) {
3057 ALOGD("BT SCO/A2DP disconnected while in connection");
3058 out_standby_l(&usecase->stream.out->stream.common);
3059 }
3060 }
3061 } else if ((usecase->stream.out != NULL) &&
3062 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303063 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3064 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003065 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303066 usecase->stream.out->started) {
3067 if (is_bt_soc_on(adev) == false) {
3068 ALOGD("BT SCO/A2dp disconnected while in connection");
3069 out_standby_l(&usecase->stream.out->stream.common);
3070 }
3071 }
3072 }
3073
Yung Ti Su70cb8242018-06-22 17:38:47 +08003074 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003075 struct stream_out *voip_out = voip_usecase->stream.out;
3076 audio_extn_utils_send_app_type_gain(adev,
3077 voip_out->app_type_cfg.app_type,
3078 &voip_out->app_type_cfg.gain[0]);
3079 }
3080
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003081 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 return status;
3084}
3085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086static int stop_input_stream(struct stream_in *in)
3087{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303088 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303090
3091 if (in == NULL) {
3092 ALOGE("%s: stream_in ptr is NULL", __func__);
3093 return -EINVAL;
3094 }
3095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003097 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098
Eric Laurent994a6932013-07-17 11:51:42 -07003099 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003100 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 uc_info = get_usecase_from_list(adev, in->usecase);
3102 if (uc_info == NULL) {
3103 ALOGE("%s: Could not find the usecase (%d) in the list",
3104 __func__, in->usecase);
3105 return -EINVAL;
3106 }
3107
Carter Hsu2e429db2019-05-14 18:50:52 +08003108 priority_in = get_priority_input(adev);
3109
Derek Chenea197282019-01-07 17:35:01 -08003110 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3111 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003112
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003113 /* Close in-call recording streams */
3114 voice_check_and_stop_incall_rec_usecase(adev, in);
3115
Eric Laurent150dbfe2013-02-27 14:31:02 -08003116 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003117 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003118
3119 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003120 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003122 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303123 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3124
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003125 list_remove(&uc_info->list);
3126 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127
Carter Hsu2e429db2019-05-14 18:50:52 +08003128 if (priority_in == in) {
3129 priority_in = get_priority_input(adev);
3130 if (priority_in)
3131 select_devices(adev, priority_in->usecase);
3132 }
3133
Vatsal Buchac09ae062018-11-14 13:25:08 +05303134 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003135 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 return ret;
3137}
3138
3139int start_input_stream(struct stream_in *in)
3140{
3141 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003142 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303144
3145 if (in == NULL) {
3146 ALOGE("%s: stream_in ptr is NULL", __func__);
3147 return -EINVAL;
3148 }
3149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003151 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003152 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153
Mingming Yin2664a5b2015-09-03 10:53:11 -07003154 if (get_usecase_from_list(adev, usecase) == NULL)
3155 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303156 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3157 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003158
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303159 if (CARD_STATUS_OFFLINE == in->card_status||
3160 CARD_STATUS_OFFLINE == adev->card_status) {
3161 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303162 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303163 goto error_config;
3164 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303165
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003166 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303167 if (!adev->bt_sco_on) {
3168 ALOGE("%s: SCO profile is not ready, return error", __func__);
3169 ret = -EIO;
3170 goto error_config;
3171 }
3172 }
3173
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003174 /* Check if source matches incall recording usecase criteria */
3175 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3176 if (ret)
3177 goto error_config;
3178 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003179 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3180
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303181 if (audio_extn_cin_attached_usecase(in))
3182 audio_extn_cin_acquire_usecase(in);
3183
Mingming Yin2664a5b2015-09-03 10:53:11 -07003184 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3185 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3186 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003187 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003188 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003189
Eric Laurentb23d5282013-05-14 15:27:20 -07003190 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 if (in->pcm_device_id < 0) {
3192 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3193 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003194 ret = -EINVAL;
3195 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003199
3200 if (!uc_info) {
3201 ret = -ENOMEM;
3202 goto error_config;
3203 }
3204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 uc_info->id = in->usecase;
3206 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003207 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003208 list_init(&uc_info->device_list);
3209 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003210 uc_info->in_snd_device = SND_DEVICE_NONE;
3211 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003213 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003214 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303215 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3216 adev->perf_lock_opts,
3217 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003218 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219
Derek Chenea197282019-01-07 17:35:01 -08003220 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3221 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003222
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303223 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3224
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303225 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303226 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303227 if (ret)
3228 goto error_open;
3229 else
3230 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003231 }
3232
Haynes Mathew George16081042017-05-31 17:16:49 -07003233 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003234 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003235 ALOGE("%s: pcm stream not ready", __func__);
3236 goto error_open;
3237 }
3238 ret = pcm_start(in->pcm);
3239 if (ret < 0) {
3240 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3241 goto error_open;
3242 }
3243 } else {
3244 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3245 unsigned int pcm_open_retry_count = 0;
3246
Zhou Song62ea0282020-03-22 19:53:01 +08003247 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3248 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003249 flags |= PCM_MMAP | PCM_NOIRQ;
3250 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3251 } else if (in->realtime) {
3252 flags |= PCM_MMAP | PCM_NOIRQ;
3253 }
3254
Garmond Leunge2433c32017-09-28 21:51:22 -07003255 if (audio_extn_ffv_get_stream() == in) {
3256 ALOGD("%s: ffv stream, update pcm config", __func__);
3257 audio_extn_ffv_update_pcm_config(&config);
3258 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003259 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3260 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3261
3262 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003263 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003264 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003265 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003266 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303267 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303268 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3269 adev->card_status = CARD_STATUS_OFFLINE;
3270 in->card_status = CARD_STATUS_OFFLINE;
3271 ret = -EIO;
3272 goto error_open;
3273 }
3274
Haynes Mathew George16081042017-05-31 17:16:49 -07003275 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3276 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3277 if (in->pcm != NULL) {
3278 pcm_close(in->pcm);
3279 in->pcm = NULL;
3280 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003281 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003282 ret = -EIO;
3283 goto error_open;
3284 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003285 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003286 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3287 continue;
3288 }
3289 break;
3290 }
3291
3292 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003293 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003294 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003295 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003296 if (ret < 0) {
3297 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3298 pcm_close(in->pcm);
3299 in->pcm = NULL;
3300 goto error_open;
3301 }
3302 register_in_stream(in);
3303 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003304 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003305 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003306 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003307 if (ret < 0) {
3308 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003309 pcm_close(in->pcm);
3310 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003311 goto error_open;
3312 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003313 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003314 }
3315
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003316 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003317 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3318 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003319
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003320 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303321 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3322
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303323done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003324 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303325 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003326 ALOGV("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303327 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003328 return ret;
3329
3330error_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);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003334
Eric Laurentc8400632013-02-14 19:04:54 -08003335error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303336 /*
3337 * sleep 50ms to allow sufficient time for kernel
3338 * drivers to recover incases like SSR.
3339 */
3340 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003341 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303342 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344}
3345
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003346void lock_input_stream(struct stream_in *in)
3347{
3348 pthread_mutex_lock(&in->pre_lock);
3349 pthread_mutex_lock(&in->lock);
3350 pthread_mutex_unlock(&in->pre_lock);
3351}
3352
3353void lock_output_stream(struct stream_out *out)
3354{
3355 pthread_mutex_lock(&out->pre_lock);
3356 pthread_mutex_lock(&out->lock);
3357 pthread_mutex_unlock(&out->pre_lock);
3358}
3359
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360/* must be called with out->lock locked */
3361static int send_offload_cmd_l(struct stream_out* out, int command)
3362{
3363 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3364
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003365 if (!cmd) {
3366 ALOGE("failed to allocate mem for command 0x%x", command);
3367 return -ENOMEM;
3368 }
3369
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003370 ALOGVV("%s %d", __func__, command);
3371
3372 cmd->cmd = command;
3373 list_add_tail(&out->offload_cmd_list, &cmd->node);
3374 pthread_cond_signal(&out->offload_cond);
3375 return 0;
3376}
3377
3378/* must be called iwth out->lock locked */
3379static void stop_compressed_output_l(struct stream_out *out)
3380{
3381 out->offload_state = OFFLOAD_STATE_IDLE;
3382 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003383 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384 if (out->compr != NULL) {
3385 compress_stop(out->compr);
3386 while (out->offload_thread_blocked) {
3387 pthread_cond_wait(&out->cond, &out->lock);
3388 }
3389 }
3390}
3391
Varun Balaraje49253e2017-07-06 19:48:56 +05303392bool is_interactive_usecase(audio_usecase_t uc_id)
3393{
3394 unsigned int i;
3395 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3396 if (uc_id == interactive_usecases[i])
3397 return true;
3398 }
3399 return false;
3400}
3401
3402static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3403{
3404 audio_usecase_t ret_uc = USECASE_INVALID;
3405 unsigned int intract_uc_index;
3406 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3407
3408 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3409 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3410 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3411 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3412 ret_uc = interactive_usecases[intract_uc_index];
3413 break;
3414 }
3415 }
3416
3417 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3418 return ret_uc;
3419}
3420
3421static void free_interactive_usecase(struct audio_device *adev,
3422 audio_usecase_t uc_id)
3423{
3424 unsigned int interact_uc_index;
3425 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3426
3427 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3428 if (interactive_usecases[interact_uc_index] == uc_id) {
3429 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3430 break;
3431 }
3432 }
3433 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3434}
3435
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003436bool is_offload_usecase(audio_usecase_t uc_id)
3437{
3438 unsigned int i;
3439 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3440 if (uc_id == offload_usecases[i])
3441 return true;
3442 }
3443 return false;
3444}
3445
Dhananjay Kumarac341582017-02-23 23:42:25 +05303446static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003447{
vivek mehta446c3962015-09-14 10:57:35 -07003448 audio_usecase_t ret_uc = USECASE_INVALID;
3449 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003450 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003451 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303452 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003453 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3454 else
3455 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003456
vivek mehta446c3962015-09-14 10:57:35 -07003457 pthread_mutex_lock(&adev->lock);
3458 if (get_usecase_from_list(adev, ret_uc) != NULL)
3459 ret_uc = USECASE_INVALID;
3460 pthread_mutex_unlock(&adev->lock);
3461
3462 return ret_uc;
3463 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464
3465 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003466 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3467 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3468 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3469 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003470 break;
3471 }
3472 }
vivek mehta446c3962015-09-14 10:57:35 -07003473
3474 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3475 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003476}
3477
3478static void free_offload_usecase(struct audio_device *adev,
3479 audio_usecase_t uc_id)
3480{
vivek mehta446c3962015-09-14 10:57:35 -07003481 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003482 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003483
3484 if (!adev->multi_offload_enable)
3485 return;
3486
3487 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3488 if (offload_usecases[offload_uc_index] == uc_id) {
3489 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003490 break;
3491 }
3492 }
3493 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3494}
3495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496static void *offload_thread_loop(void *context)
3497{
3498 struct stream_out *out = (struct stream_out *) context;
3499 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003500 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003503 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3505
3506 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003507 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003508 out->offload_state = OFFLOAD_STATE_IDLE;
3509 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 for (;;) {
3511 struct offload_cmd *cmd = NULL;
3512 stream_callback_event_t event;
3513 bool send_callback = false;
3514
3515 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3516 __func__, list_empty(&out->offload_cmd_list),
3517 out->offload_state);
3518 if (list_empty(&out->offload_cmd_list)) {
3519 ALOGV("%s SLEEPING", __func__);
3520 pthread_cond_wait(&out->offload_cond, &out->lock);
3521 ALOGV("%s RUNNING", __func__);
3522 continue;
3523 }
3524
3525 item = list_head(&out->offload_cmd_list);
3526 cmd = node_to_item(item, struct offload_cmd, node);
3527 list_remove(item);
3528
3529 ALOGVV("%s STATE %d CMD %d out->compr %p",
3530 __func__, out->offload_state, cmd->cmd, out->compr);
3531
3532 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3533 free(cmd);
3534 break;
3535 }
3536
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003537 // allow OFFLOAD_CMD_ERROR reporting during standby
3538 // this is needed to handle failures during compress_open
3539 // Note however that on a pause timeout, the stream is closed
3540 // and no offload usecase will be active. Therefore this
3541 // special case is needed for compress_open failures alone
3542 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3543 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003544 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003545 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003546 pthread_cond_signal(&out->cond);
3547 continue;
3548 }
3549 out->offload_thread_blocked = true;
3550 pthread_mutex_unlock(&out->lock);
3551 send_callback = false;
3552 switch(cmd->cmd) {
3553 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003554 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003556 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 send_callback = true;
3558 event = STREAM_CBK_EVENT_WRITE_READY;
3559 break;
3560 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003561 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303562 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003563 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303564 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003565 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303566 if (ret < 0)
3567 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303568 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303569 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003570 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003571 else
3572 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003573 if (-ENETRESET != ret && !(-EINTR == ret &&
3574 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303575 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303576 pthread_mutex_lock(&out->lock);
3577 out->send_new_metadata = 1;
3578 out->send_next_track_params = true;
3579 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303580 event = STREAM_CBK_EVENT_DRAIN_READY;
3581 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3582 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303583 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 break;
3585 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003586 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003587 ret = compress_drain(out->compr);
3588 ALOGD("copl(%p):out of compress_drain", out);
3589 // EINTR check avoids drain interruption due to SSR
3590 if (-ENETRESET != ret && !(-EINTR == ret &&
3591 CARD_STATUS_OFFLINE == out->card_status)) {
3592 send_callback = true;
3593 event = STREAM_CBK_EVENT_DRAIN_READY;
3594 } else
3595 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303597 case OFFLOAD_CMD_ERROR:
3598 ALOGD("copl(%p): sending error callback to AF", out);
3599 send_callback = true;
3600 event = STREAM_CBK_EVENT_ERROR;
3601 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003602 default:
3603 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3604 break;
3605 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003606 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003607 out->offload_thread_blocked = false;
3608 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003609 if (send_callback && out->client_callback) {
3610 ALOGVV("%s: sending client_callback event %d", __func__, event);
3611 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003612 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003613 free(cmd);
3614 }
3615
3616 pthread_cond_signal(&out->cond);
3617 while (!list_empty(&out->offload_cmd_list)) {
3618 item = list_head(&out->offload_cmd_list);
3619 list_remove(item);
3620 free(node_to_item(item, struct offload_cmd, node));
3621 }
3622 pthread_mutex_unlock(&out->lock);
3623
3624 return NULL;
3625}
3626
3627static int create_offload_callback_thread(struct stream_out *out)
3628{
3629 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3630 list_init(&out->offload_cmd_list);
3631 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3632 offload_thread_loop, out);
3633 return 0;
3634}
3635
3636static int destroy_offload_callback_thread(struct stream_out *out)
3637{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003638 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003639 stop_compressed_output_l(out);
3640 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3641
3642 pthread_mutex_unlock(&out->lock);
3643 pthread_join(out->offload_thread, (void **) NULL);
3644 pthread_cond_destroy(&out->offload_cond);
3645
3646 return 0;
3647}
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649static int stop_output_stream(struct stream_out *out)
3650{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303651 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 struct audio_usecase *uc_info;
3653 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003654 bool has_voip_usecase =
3655 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Eric Laurent994a6932013-07-17 11:51:42 -07003657 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003658 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 uc_info = get_usecase_from_list(adev, out->usecase);
3660 if (uc_info == NULL) {
3661 ALOGE("%s: Could not find the usecase (%d) in the list",
3662 __func__, out->usecase);
3663 return -EINVAL;
3664 }
3665
Derek Chenea197282019-01-07 17:35:01 -08003666 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3667 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003668
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003669 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303670 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003671 if (adev->visualizer_stop_output != NULL)
3672 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003673
3674 audio_extn_dts_remove_state_notifier_node(out->usecase);
3675
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003676 if (adev->offload_effects_stop_output != NULL)
3677 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003678 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3679 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3680 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003681 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003682
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003683 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3684 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003685 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003686 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003687
Eric Laurent150dbfe2013-02-27 14:31:02 -08003688 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003689 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003690
3691 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003692 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003693 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3694 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695
Aalique Grahame22e49102018-12-18 14:23:57 -08003696 audio_extn_extspk_update(adev->extspk);
3697
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003698 if (is_offload_usecase(out->usecase)) {
3699 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3700 adev->dsp_bit_width_enforce_mode,
3701 false);
3702 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003703 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003704 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3705 false);
3706
3707 if (ret != 0)
3708 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3709 /* default service interval was successfully updated,
3710 reopen USB backend with new service interval */
3711 ret = 0;
3712 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003713
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003714 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303715 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003716 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303717 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003718 ALOGV("Disable passthrough , reset mixer to pcm");
3719 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003720#ifdef AUDIO_GKI_ENABLED
3721 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3722 out->compr_config.codec->reserved[0] = 0;
3723#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003724 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003725#endif
Mingming Yin21854652016-04-13 11:54:02 -07003726 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003727 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3728 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003729
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303730 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003731 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303732 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303733
Manish Dewangan21a850a2017-08-14 12:03:55 +05303734 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003735 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3736 if (ret < 0)
3737 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3738 }
3739
juyuchen2d415992018-11-16 14:15:16 +08003740 /* 1) media + voip output routing to handset must route media back to
3741 speaker when voip stops.
3742 2) trigger voip input to reroute when voip output changes to
3743 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003744 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003745 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003746 struct listnode *node;
3747 struct audio_usecase *usecase;
3748 list_for_each(node, &adev->usecase_list) {
3749 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003750 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303751 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3752 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003753 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003754 continue;
3755
3756 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3757 __func__, usecase->id, use_case_table[usecase->id],
3758 out->usecase, use_case_table[out->usecase]);
3759 select_devices(adev, usecase->id);
3760 }
3761 }
3762
Garmond Leung5fd0b552018-04-17 11:56:12 -07003763 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003764 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 return ret;
3766}
3767
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003768struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3769 unsigned int flags, unsigned int pcm_open_retry_count,
3770 struct pcm_config *config)
3771{
3772 struct pcm* pcm = NULL;
3773
3774 while (1) {
3775 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3776 if (pcm == NULL || !pcm_is_ready(pcm)) {
3777 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3778 if (pcm != NULL) {
3779 pcm_close(pcm);
3780 pcm = NULL;
3781 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003782 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003783 return NULL;
3784
Weiyin Jiang72197252019-10-09 11:49:32 +08003785 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003786 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3787 continue;
3788 }
3789 break;
3790 }
3791
3792 if (pcm_is_ready(pcm)) {
3793 int ret = pcm_prepare(pcm);
3794 if (ret < 0) {
3795 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3796 pcm_close(pcm);
3797 pcm = NULL;
3798 }
3799 }
3800
3801 return pcm;
3802}
3803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804int start_output_stream(struct stream_out *out)
3805{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 struct audio_usecase *uc_info;
3808 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003809 char mixer_ctl_name[128];
3810 struct mixer_ctl *ctl = NULL;
3811 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303812 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003813 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Haynes Mathew George380745d2017-10-04 15:27:45 -07003815 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003816 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3817 ret = -EINVAL;
3818 goto error_config;
3819 }
3820
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003821 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303822 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003823 get_device_types(&out->device_list), is_haptic_usecase);
3824
3825 bool is_speaker_active = compare_device_type(&out->device_list,
3826 AUDIO_DEVICE_OUT_SPEAKER);
3827 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3828 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303829
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303830 if (CARD_STATUS_OFFLINE == out->card_status ||
3831 CARD_STATUS_OFFLINE == adev->card_status) {
3832 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303833 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003834 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303835 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303836
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003837 //Update incall music usecase to reflect correct voice session
3838 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3839 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3840 if (ret != 0) {
3841 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3842 __func__, ret);
3843 goto error_config;
3844 }
3845 }
3846
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003847 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003848 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003849 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303850 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303851 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303852 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3853 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3854 ret = -EAGAIN;
3855 goto error_config;
3856 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303857 }
3858 }
3859 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003860 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303861 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003862 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303863 //combo usecase just by pass a2dp
3864 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003865 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303866 } else {
3867 ALOGE("%s: SCO profile is not ready, return error", __func__);
3868 ret = -EAGAIN;
3869 goto error_config;
3870 }
3871 }
3872 }
3873
Eric Laurentb23d5282013-05-14 15:27:20 -07003874 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875 if (out->pcm_device_id < 0) {
3876 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3877 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003878 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003879 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880 }
3881
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003883 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3884 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003885 if (adev->haptic_pcm_device_id < 0) {
3886 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3887 __func__, adev->haptic_pcm_device_id, out->usecase);
3888 ret = -EINVAL;
3889 goto error_config;
3890 }
3891 }
3892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003894
3895 if (!uc_info) {
3896 ret = -ENOMEM;
3897 goto error_config;
3898 }
3899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 uc_info->id = out->usecase;
3901 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003902 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003903 list_init(&uc_info->device_list);
3904 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003905 uc_info->in_snd_device = SND_DEVICE_NONE;
3906 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003907
3908 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003909 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003910 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3911 /* USB backend is not reopened immediately.
3912 This is eventually done as part of select_devices */
3913 }
3914
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003915 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916
Wei Wangf7ca6c92017-11-21 14:51:20 -08003917 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303918 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3919 adev->perf_lock_opts,
3920 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303921
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003922 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303923 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303924 if (audio_extn_passthru_is_enabled() &&
3925 audio_extn_passthru_is_passthrough_stream(out)) {
3926 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303927 }
3928 }
3929
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003930 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003931 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303932 if (!a2dp_combo) {
3933 check_a2dp_restore_l(adev, out, false);
3934 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003935 struct listnode dev;
3936 list_init(&dev);
3937 assign_devices(&dev, &out->device_list);
3938 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3939 reassign_device_list(&out->device_list,
3940 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003941 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003942 reassign_device_list(&out->device_list,
3943 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303944 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003945 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303946 }
3947 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303948 select_devices(adev, out->usecase);
3949 if (is_a2dp_out_device_type(&out->device_list) &&
3950 !adev->a2dp_started) {
3951 if (is_speaker_active || is_speaker_safe_active) {
3952 struct listnode dev;
3953 list_init(&dev);
3954 assign_devices(&dev, &out->device_list);
3955 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3956 reassign_device_list(&out->device_list,
3957 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3958 else
3959 reassign_device_list(&out->device_list,
3960 AUDIO_DEVICE_OUT_SPEAKER, "");
3961 select_devices(adev, out->usecase);
3962 assign_devices(&out->device_list, &dev);
3963 } else {
3964 ret = -EINVAL;
3965 goto error_open;
3966 }
3967 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303968 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003969
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003970 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3971 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003972 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003973 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003974
Derek Chenea197282019-01-07 17:35:01 -08003975 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3976 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003977
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003978 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3979 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003980
3981 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003982 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003983 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3984 ALOGE("%s: pcm stream not ready", __func__);
3985 goto error_open;
3986 }
3987 ret = pcm_start(out->pcm);
3988 if (ret < 0) {
3989 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3990 goto error_open;
3991 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003992 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003993 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003994 unsigned int flags = PCM_OUT;
3995 unsigned int pcm_open_retry_count = 0;
3996 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3997 flags |= PCM_MMAP | PCM_NOIRQ;
3998 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003999 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004000 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004001 } else
4002 flags |= PCM_MONOTONIC;
4003
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004004 if ((adev->vr_audio_mode_enabled) &&
4005 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4006 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4007 "PCM_Dev %d Topology", out->pcm_device_id);
4008 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4009 if (!ctl) {
4010 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4011 __func__, mixer_ctl_name);
4012 } else {
4013 //if success use ULLPP
4014 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4015 __func__, mixer_ctl_name, out->pcm_device_id);
4016 //There is a still a possibility that some sessions
4017 // that request for FAST|RAW when 3D audio is active
4018 //can go through ULLPP. Ideally we expects apps to
4019 //listen to audio focus and stop concurrent playback
4020 //Also, we will look for mode flag (voice_in_communication)
4021 //before enabling the realtime flag.
4022 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4023 }
4024 }
4025
Surendar Karka91fa3682018-07-02 18:12:12 +05304026 if (out->realtime)
4027 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4028 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4029
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004030 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4031 flags, pcm_open_retry_count,
4032 &(out->config));
4033 if (out->pcm == NULL) {
4034 ret = -EIO;
4035 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004037
4038 if (is_haptic_usecase) {
4039 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4040 adev->haptic_pcm_device_id,
4041 flags, pcm_open_retry_count,
4042 &(adev->haptics_config));
4043 // failure to open haptics pcm shouldnt stop audio,
4044 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004045
4046 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4047 ALOGD("%s: enable haptic audio synchronization", __func__);
4048 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4049 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004050 }
4051
Surendar Karka91fa3682018-07-02 18:12:12 +05304052 if (!out->realtime)
4053 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304054 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004055
Zhou Song2b8f28f2017-09-11 10:51:38 +08004056 // apply volume for voip playback after path is set up
4057 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4058 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304059 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4060 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304061 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4062 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004063 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4064 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304065 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004067 /*
4068 * set custom channel map if:
4069 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4070 * 2. custom channel map has been set by client
4071 * else default channel map of FC/FR/FL can always be set to DSP
4072 */
4073 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4074 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4075 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004076 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4077 adev->dsp_bit_width_enforce_mode,
4078 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004080 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004081 out->compr = compress_open(adev->snd_card,
4082 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004083 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004084 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304085 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304086 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4087 adev->card_status = CARD_STATUS_OFFLINE;
4088 out->card_status = CARD_STATUS_OFFLINE;
4089 ret = -EIO;
4090 goto error_open;
4091 }
4092
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004093 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004094 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004095 compress_close(out->compr);
4096 out->compr = NULL;
4097 ret = -EIO;
4098 goto error_open;
4099 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304100 /* compress_open sends params of the track, so reset the flag here */
4101 out->is_compr_metadata_avail = false;
4102
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004103 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004104 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004105
Fred Oh3f43e742015-03-04 18:42:34 -08004106 /* Since small bufs uses blocking writes, a write will be blocked
4107 for the default max poll time (20s) in the event of an SSR.
4108 Reduce the poll time to observe and deal with SSR faster.
4109 */
Ashish Jain5106d362016-05-11 19:23:33 +05304110 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004111 compress_set_max_poll_wait(out->compr, 1000);
4112 }
4113
Manish Dewangan69426c82017-01-30 17:35:36 +05304114 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304115 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304116
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004117 audio_extn_dts_create_state_notifier_node(out->usecase);
4118 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4119 popcount(out->channel_mask),
4120 out->playback_started);
4121
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004122#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304123 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004124 audio_extn_dolby_send_ddp_endp_params(adev);
4125#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304126 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4127 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004128 if (adev->visualizer_start_output != NULL)
4129 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4130 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304131 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004132 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004133 }
Derek Chenf13dd492018-11-13 14:53:51 -08004134
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004135 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004136 /* Update cached volume from media to offload/direct stream */
4137 struct listnode *node = NULL;
4138 list_for_each(node, &adev->active_outputs_list) {
4139 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4140 streams_output_ctxt_t,
4141 list);
4142 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4143 out->volume_l = out_ctxt->output->volume_l;
4144 out->volume_r = out_ctxt->output->volume_r;
4145 }
4146 }
4147 out_set_compr_volume(&out->stream,
4148 out->volume_l, out->volume_r);
4149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004151
4152 if (ret == 0) {
4153 register_out_stream(out);
4154 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004155 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4156 ALOGE("%s: pcm stream not ready", __func__);
4157 goto error_open;
4158 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004159 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004160 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004161 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004162 if (ret < 0)
4163 goto error_open;
4164 }
4165 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004166 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304167 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004168 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004169
vivek mehtad15d2bf2019-05-17 13:35:10 -07004170 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4171 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4172 audio_low_latency_hint_start();
4173 }
4174
Manish Dewangan21a850a2017-08-14 12:03:55 +05304175 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004176 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004177 if (ret < 0)
4178 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4179 }
4180
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004181 // consider a scenario where on pause lower layers are tear down.
4182 // so on resume, swap mixer control need to be sent only when
4183 // backend is active, hence rather than sending from enable device
4184 // sending it from start of streamtream
4185
4186 platform_set_swap_channels(adev, true);
4187
Haynes Mathew George380745d2017-10-04 15:27:45 -07004188 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304189 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004190 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004191error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004192 if (adev->haptic_pcm) {
4193 pcm_close(adev->haptic_pcm);
4194 adev->haptic_pcm = NULL;
4195 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004196 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304197 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004199error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304200 /*
4201 * sleep 50ms to allow sufficient time for kernel
4202 * drivers to recover incases like SSR.
4203 */
4204 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004205error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004206 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304207 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004208 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209}
4210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211static int check_input_parameters(uint32_t sample_rate,
4212 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004213 int channel_count,
4214 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004216 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304218 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4219 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4220 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004221 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004222 !audio_extn_compr_cap_format_supported(format) &&
4223 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004224 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004225
Aalique Grahame22e49102018-12-18 14:23:57 -08004226 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4227 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4228 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4229 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4230 return -EINVAL;
4231 }
4232
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004233 switch (channel_count) {
4234 case 1:
4235 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304236 case 3:
4237 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004238 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004239 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304240 case 10:
4241 case 12:
4242 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004243 break;
4244 default:
4245 ret = -EINVAL;
4246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247
4248 switch (sample_rate) {
4249 case 8000:
4250 case 11025:
4251 case 12000:
4252 case 16000:
4253 case 22050:
4254 case 24000:
4255 case 32000:
4256 case 44100:
4257 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004258 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304259 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004260 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304261 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 break;
4263 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004264 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265 }
4266
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004267 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268}
4269
Naresh Tanniru04f71882018-06-26 17:46:22 +05304270
4271/** Add a value in a list if not already present.
4272 * @return true if value was successfully inserted or already present,
4273 * false if the list is full and does not contain the value.
4274 */
4275static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4276 for (size_t i = 0; i < list_length; i++) {
4277 if (list[i] == value) return true; // value is already present
4278 if (list[i] == 0) { // no values in this slot
4279 list[i] = value;
4280 return true; // value inserted
4281 }
4282 }
4283 return false; // could not insert value
4284}
4285
4286/** Add channel_mask in supported_channel_masks if not already present.
4287 * @return true if channel_mask was successfully inserted or already present,
4288 * false if supported_channel_masks is full and does not contain channel_mask.
4289 */
4290static void register_channel_mask(audio_channel_mask_t channel_mask,
4291 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4292 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4293 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4294}
4295
4296/** Add format in supported_formats if not already present.
4297 * @return true if format was successfully inserted or already present,
4298 * false if supported_formats is full and does not contain format.
4299 */
4300static void register_format(audio_format_t format,
4301 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4302 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4303 "%s: stream can not declare supporting its format %x", __func__, format);
4304}
4305/** Add sample_rate in supported_sample_rates if not already present.
4306 * @return true if sample_rate was successfully inserted or already present,
4307 * false if supported_sample_rates is full and does not contain sample_rate.
4308 */
4309static void register_sample_rate(uint32_t sample_rate,
4310 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4311 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4312 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4313}
4314
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004315static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4316{
4317 uint32_t high = num1, low = num2, temp = 0;
4318
4319 if (!num1 || !num2)
4320 return 0;
4321
4322 if (num1 < num2) {
4323 high = num2;
4324 low = num1;
4325 }
4326
4327 while (low != 0) {
4328 temp = low;
4329 low = high % low;
4330 high = temp;
4331 }
4332 return (num1 * num2)/high;
4333}
4334
4335static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4336{
4337 uint32_t remainder = 0;
4338
4339 if (!multiplier)
4340 return num;
4341
4342 remainder = num % multiplier;
4343 if (remainder)
4344 num += (multiplier - remainder);
4345
4346 return num;
4347}
4348
Aalique Grahame22e49102018-12-18 14:23:57 -08004349static size_t get_stream_buffer_size(size_t duration_ms,
4350 uint32_t sample_rate,
4351 audio_format_t format,
4352 int channel_count,
4353 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354{
4355 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004356 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357
Aalique Grahame22e49102018-12-18 14:23:57 -08004358 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004359 if (is_low_latency)
4360 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304361
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004362 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004363 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364
Ralf Herzbd08d632018-09-28 15:50:49 +02004365 /* make sure the size is multiple of 32 bytes and additionally multiple of
4366 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004367 * At 48 kHz mono 16-bit PCM:
4368 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4369 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004370 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004371 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004372 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004373
4374 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375}
4376
Aalique Grahame22e49102018-12-18 14:23:57 -08004377static size_t get_input_buffer_size(uint32_t sample_rate,
4378 audio_format_t format,
4379 int channel_count,
4380 bool is_low_latency)
4381{
4382 /* Don't know if USB HIFI in this context so use true to be conservative */
4383 if (check_input_parameters(sample_rate, format, channel_count,
4384 true /*is_usb_hifi */) != 0)
4385 return 0;
4386
4387 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4388 sample_rate,
4389 format,
4390 channel_count,
4391 is_low_latency);
4392}
4393
Derek Chenf6318be2017-06-12 17:16:24 -04004394size_t get_output_period_size(uint32_t sample_rate,
4395 audio_format_t format,
4396 int channel_count,
4397 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304398{
4399 size_t size = 0;
4400 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4401
4402 if ((duration == 0) || (sample_rate == 0) ||
4403 (bytes_per_sample == 0) || (channel_count == 0)) {
4404 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4405 bytes_per_sample, channel_count);
4406 return -EINVAL;
4407 }
4408
4409 size = (sample_rate *
4410 duration *
4411 bytes_per_sample *
4412 channel_count) / 1000;
4413 /*
4414 * To have same PCM samples for all channels, the buffer size requires to
4415 * be multiple of (number of channels * bytes per sample)
4416 * For writes to succeed, the buffer must be written at address which is multiple of 32
4417 */
4418 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4419
4420 return (size/(channel_count * bytes_per_sample));
4421}
4422
Zhou Song48453a02018-01-10 17:50:59 +08004423static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304424{
4425 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004426 uint64_t written_frames = 0;
4427 uint64_t kernel_frames = 0;
4428 uint64_t dsp_frames = 0;
4429 uint64_t signed_frames = 0;
4430 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304431
4432 /* This adjustment accounts for buffering after app processor.
4433 * It is based on estimated DSP latency per use case, rather than exact.
4434 */
George Gao9ba8a142020-07-23 14:30:03 -07004435 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004436 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304437
Zhou Song48453a02018-01-10 17:50:59 +08004438 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004439 written_frames = out->written /
4440 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4441
Ashish Jain5106d362016-05-11 19:23:33 +05304442 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4443 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4444 * hence only estimate.
4445 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004446 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4447 kernel_frames = kernel_buffer_size /
4448 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304449
Weiyin Jiang4813da12020-05-28 00:37:28 +08004450 if (written_frames >= (kernel_frames + dsp_frames))
4451 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304452
Zhou Song48453a02018-01-10 17:50:59 +08004453 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304454 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004455 if (timestamp != NULL )
4456 *timestamp = out->writeAt;
4457 } else if (timestamp != NULL) {
4458 clock_gettime(CLOCK_MONOTONIC, timestamp);
4459 }
4460 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304461
Weiyin Jiang4813da12020-05-28 00:37:28 +08004462 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4463 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304464
4465 return actual_frames_rendered;
4466}
4467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4469{
4470 struct stream_out *out = (struct stream_out *)stream;
4471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004472 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473}
4474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004475static int out_set_sample_rate(struct audio_stream *stream __unused,
4476 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477{
4478 return -ENOSYS;
4479}
4480
4481static size_t out_get_buffer_size(const struct audio_stream *stream)
4482{
4483 struct stream_out *out = (struct stream_out *)stream;
4484
Varun Balaraje49253e2017-07-06 19:48:56 +05304485 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304486 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304487 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304488 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4489 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4490 else
4491 return out->compr_config.fragment_size;
4492 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004493 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304494 else if (is_offload_usecase(out->usecase) &&
4495 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304496 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004497
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004498 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004499 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500}
4501
4502static uint32_t out_get_channels(const struct audio_stream *stream)
4503{
4504 struct stream_out *out = (struct stream_out *)stream;
4505
4506 return out->channel_mask;
4507}
4508
4509static audio_format_t out_get_format(const struct audio_stream *stream)
4510{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004511 struct stream_out *out = (struct stream_out *)stream;
4512
4513 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514}
4515
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004516static int out_set_format(struct audio_stream *stream __unused,
4517 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518{
4519 return -ENOSYS;
4520}
4521
4522static int out_standby(struct audio_stream *stream)
4523{
4524 struct stream_out *out = (struct stream_out *)stream;
4525 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004526 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004527
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304528 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4529 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004531 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004533 if (adev->adm_deregister_stream)
4534 adev->adm_deregister_stream(adev->adm_data, out->handle);
4535
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004536 if (is_offload_usecase(out->usecase))
4537 stop_compressed_output_l(out);
4538
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004539 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004541 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4542 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304543 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004544 pthread_mutex_unlock(&adev->lock);
4545 pthread_mutex_unlock(&out->lock);
4546 ALOGD("VOIP output entered standby");
4547 return 0;
4548 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004549 if (out->pcm) {
4550 pcm_close(out->pcm);
4551 out->pcm = NULL;
4552 }
Meng Wanga09da002020-04-20 12:56:04 +08004553 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4554 if (adev->haptic_pcm) {
4555 pcm_close(adev->haptic_pcm);
4556 adev->haptic_pcm = NULL;
4557 }
4558
4559 if (adev->haptic_buffer != NULL) {
4560 free(adev->haptic_buffer);
4561 adev->haptic_buffer = NULL;
4562 adev->haptic_buffer_size = 0;
4563 }
4564 adev->haptic_pcm_device_id = 0;
4565 }
4566
Haynes Mathew George16081042017-05-31 17:16:49 -07004567 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4568 do_stop = out->playback_started;
4569 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004570
4571 if (out->mmap_shared_memory_fd >= 0) {
4572 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4573 __func__, out->mmap_shared_memory_fd);
4574 close(out->mmap_shared_memory_fd);
4575 out->mmap_shared_memory_fd = -1;
4576 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004577 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004578 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004579 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304580 out->send_next_track_params = false;
4581 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004582 out->gapless_mdata.encoder_delay = 0;
4583 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004584 if (out->compr != NULL) {
4585 compress_close(out->compr);
4586 out->compr = NULL;
4587 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004588 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004589 if (do_stop) {
4590 stop_output_stream(out);
4591 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304592 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004593 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004594 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595 }
4596 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004597 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 return 0;
4599}
4600
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304601static int out_on_error(struct audio_stream *stream)
4602{
4603 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004604 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304605
4606 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004607 // always send CMD_ERROR for offload streams, this
4608 // is needed e.g. when SSR happens within compress_open
4609 // since the stream is active, offload_callback_thread is also active.
4610 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4611 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004612 }
4613 pthread_mutex_unlock(&out->lock);
4614
4615 status = out_standby(&out->stream.common);
4616
4617 lock_output_stream(out);
4618 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004619 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304620 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304621
4622 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4623 ALOGD("Setting previous card status if offline");
4624 out->prev_card_status_offline = true;
4625 }
4626
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304627 pthread_mutex_unlock(&out->lock);
4628
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004629 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304630}
4631
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304632/*
4633 *standby implementation without locks, assumes that the callee already
4634 *has taken adev and out lock.
4635 */
4636int out_standby_l(struct audio_stream *stream)
4637{
4638 struct stream_out *out = (struct stream_out *)stream;
4639 struct audio_device *adev = out->dev;
4640
4641 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4642 stream, out->usecase, use_case_table[out->usecase]);
4643
4644 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004645 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304646 if (adev->adm_deregister_stream)
4647 adev->adm_deregister_stream(adev->adm_data, out->handle);
4648
4649 if (is_offload_usecase(out->usecase))
4650 stop_compressed_output_l(out);
4651
4652 out->standby = true;
4653 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4654 voice_extn_compress_voip_close_output_stream(stream);
4655 out->started = 0;
4656 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004657 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304658 return 0;
4659 } else if (!is_offload_usecase(out->usecase)) {
4660 if (out->pcm) {
4661 pcm_close(out->pcm);
4662 out->pcm = NULL;
4663 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004664 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4665 if (adev->haptic_pcm) {
4666 pcm_close(adev->haptic_pcm);
4667 adev->haptic_pcm = NULL;
4668 }
4669
4670 if (adev->haptic_buffer != NULL) {
4671 free(adev->haptic_buffer);
4672 adev->haptic_buffer = NULL;
4673 adev->haptic_buffer_size = 0;
4674 }
4675 adev->haptic_pcm_device_id = 0;
4676 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304677 } else {
4678 ALOGD("copl(%p):standby", out);
4679 out->send_next_track_params = false;
4680 out->is_compr_metadata_avail = false;
4681 out->gapless_mdata.encoder_delay = 0;
4682 out->gapless_mdata.encoder_padding = 0;
4683 if (out->compr != NULL) {
4684 compress_close(out->compr);
4685 out->compr = NULL;
4686 }
4687 }
4688 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004689 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304690 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004691 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304692 return 0;
4693}
4694
Aalique Grahame22e49102018-12-18 14:23:57 -08004695static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696{
Aalique Grahame22e49102018-12-18 14:23:57 -08004697 struct stream_out *out = (struct stream_out *)stream;
4698
4699 // We try to get the lock for consistency,
4700 // but it isn't necessary for these variables.
4701 // If we're not in standby, we may be blocked on a write.
4702 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4703 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4704 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4705
Andy Hunga1f48fa2019-07-01 18:14:53 -07004706 char buffer[256]; // for statistics formatting
4707 if (!is_offload_usecase(out->usecase)) {
4708 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4709 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4710 }
4711
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004712 if (out->start_latency_ms.n > 0) {
4713 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4714 dprintf(fd, " Start latency ms: %s\n", buffer);
4715 }
4716
Aalique Grahame22e49102018-12-18 14:23:57 -08004717 if (locked) {
4718 pthread_mutex_unlock(&out->lock);
4719 }
4720
4721 // dump error info
4722 (void)error_log_dump(
4723 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 return 0;
4726}
4727
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004728static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4729{
4730 int ret = 0;
4731 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004732
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004733 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004734 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004735 return -EINVAL;
4736 }
4737
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304738 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004739
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004740 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4741 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304742 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004743 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004744 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4745 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304746 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004747 }
4748
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004749 ALOGV("%s new encoder delay %u and padding %u", __func__,
4750 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4751
4752 return 0;
4753}
4754
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004755static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4756{
4757 return out == adev->primary_output || out == adev->voice_tx_output;
4758}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004759
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304760// note: this call is safe only if the stream_cb is
4761// removed first in close_output_stream (as is done now).
4762static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4763{
4764 if (!stream || !parms)
4765 return;
4766
4767 struct stream_out *out = (struct stream_out *)stream;
4768 struct audio_device *adev = out->dev;
4769
4770 card_status_t status;
4771 int card;
4772 if (parse_snd_card_status(parms, &card, &status) < 0)
4773 return;
4774
4775 pthread_mutex_lock(&adev->lock);
4776 bool valid_cb = (card == adev->snd_card);
4777 pthread_mutex_unlock(&adev->lock);
4778
4779 if (!valid_cb)
4780 return;
4781
4782 lock_output_stream(out);
4783 if (out->card_status != status)
4784 out->card_status = status;
4785 pthread_mutex_unlock(&out->lock);
4786
4787 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4788 use_case_table[out->usecase],
4789 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4790
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304791 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304792 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304793 if (voice_is_call_state_active(adev) &&
4794 out == adev->primary_output) {
4795 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4796 pthread_mutex_lock(&adev->lock);
4797 voice_stop_call(adev);
4798 adev->mode = AUDIO_MODE_NORMAL;
4799 pthread_mutex_unlock(&adev->lock);
4800 }
4801 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304802 return;
4803}
4804
Kevin Rocardfce19002017-08-07 19:21:36 -07004805static int get_alive_usb_card(struct str_parms* parms) {
4806 int card;
4807 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4808 !audio_extn_usb_alive(card)) {
4809 return card;
4810 }
4811 return -ENODEV;
4812}
4813
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004814int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004815 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816{
4817 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004818 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004819 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004820 bool bypass_a2dp = false;
4821 bool reconfig = false;
4822 unsigned long service_interval = 0;
4823
4824 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004825 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4826
4827 list_init(&new_devices);
4828 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004829
4830 lock_output_stream(out);
4831 pthread_mutex_lock(&adev->lock);
4832
4833 /*
4834 * When HDMI cable is unplugged the music playback is paused and
4835 * the policy manager sends routing=0. But the audioflinger continues
4836 * to write data until standby time (3sec). As the HDMI core is
4837 * turned off, the write gets blocked.
4838 * Avoid this by routing audio to speaker until standby.
4839 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004840 if (is_single_device_type_equal(&out->device_list,
4841 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004842 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004843 !audio_extn_passthru_is_passthrough_stream(out) &&
4844 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004845 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004846 }
4847 /*
4848 * When A2DP is disconnected the
4849 * music playback is paused and the policy manager sends routing=0
4850 * But the audioflinger continues to write data until standby time
4851 * (3sec). As BT is turned off, the write gets blocked.
4852 * Avoid this by routing audio to speaker until standby.
4853 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004854 if (is_a2dp_out_device_type(&out->device_list) &&
4855 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004856 !audio_extn_a2dp_source_is_ready() &&
4857 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004858 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004859 }
4860 /*
4861 * When USB headset is disconnected the music platback paused
4862 * and the policy manager send routing=0. But if the USB is connected
4863 * back before the standby time, AFE is not closed and opened
4864 * when USB is connected back. So routing to speker will guarantee
4865 * AFE reconfiguration and AFE will be opend once USB is connected again
4866 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004867 if (is_usb_out_device_type(&out->device_list) &&
4868 list_empty(&new_devices) &&
4869 !audio_extn_usb_connected(NULL)) {
4870 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4871 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004872 /* To avoid a2dp to sco overlapping / BT device improper state
4873 * check with BT lib about a2dp streaming support before routing
4874 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004875 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004876 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004877 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4878 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004879 //combo usecase just by pass a2dp
4880 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4881 bypass_a2dp = true;
4882 } else {
4883 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4884 /* update device to a2dp and don't route as BT returned error
4885 * However it is still possible a2dp routing called because
4886 * of current active device disconnection (like wired headset)
4887 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004888 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004889 pthread_mutex_unlock(&adev->lock);
4890 pthread_mutex_unlock(&out->lock);
4891 goto error;
4892 }
4893 }
4894 }
4895
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004896 // Workaround: If routing to an non existing usb device, fail gracefully
4897 // The routing request will otherwise block during 10 second
4898 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004899 if (is_usb_out_device_type(&new_devices)) {
4900 struct str_parms *parms =
4901 str_parms_create_str(get_usb_device_address(&new_devices));
4902 if (!parms)
4903 goto error;
4904 if ((card = get_alive_usb_card(parms)) >= 0) {
4905 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4906 pthread_mutex_unlock(&adev->lock);
4907 pthread_mutex_unlock(&out->lock);
4908 str_parms_destroy(parms);
4909 ret = -ENOSYS;
4910 goto error;
4911 }
4912 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004913 }
4914
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004915 // Workaround: If routing to an non existing hdmi device, fail gracefully
4916 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4917 (platform_get_edid_info_v2(adev->platform,
4918 out->extconn.cs.controller,
4919 out->extconn.cs.stream) != 0)) {
4920 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4921 pthread_mutex_unlock(&adev->lock);
4922 pthread_mutex_unlock(&out->lock);
4923 ret = -ENOSYS;
4924 goto error;
4925 }
4926
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004927 /*
4928 * select_devices() call below switches all the usecases on the same
4929 * backend to the new device. Refer to check_usecases_codec_backend() in
4930 * the select_devices(). But how do we undo this?
4931 *
4932 * For example, music playback is active on headset (deep-buffer usecase)
4933 * and if we go to ringtones and select a ringtone, low-latency usecase
4934 * will be started on headset+speaker. As we can't enable headset+speaker
4935 * and headset devices at the same time, select_devices() switches the music
4936 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4937 * So when the ringtone playback is completed, how do we undo the same?
4938 *
4939 * We are relying on the out_set_parameters() call on deep-buffer output,
4940 * once the ringtone playback is ended.
4941 * NOTE: We should not check if the current devices are same as new devices.
4942 * Because select_devices() must be called to switch back the music
4943 * playback to headset.
4944 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004945 if (!list_empty(&new_devices)) {
4946 bool same_dev = compare_devices(&out->device_list, &new_devices);
4947 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004948
4949 if (output_drives_call(adev, out)) {
4950 if (!voice_is_call_state_active(adev)) {
4951 if (adev->mode == AUDIO_MODE_IN_CALL) {
4952 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004953 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004954 service_interval =
4955 audio_extn_usb_find_service_interval(true, true /*playback*/);
4956 audio_extn_usb_set_service_interval(true /*playback*/,
4957 service_interval,
4958 &reconfig);
4959 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4960 }
4961 ret = voice_start_call(adev);
4962 }
4963 } else {
4964 adev->current_call_output = out;
4965 voice_update_devices_for_all_voice_usecases(adev);
4966 }
4967 }
4968
4969 if (!out->standby) {
4970 if (!same_dev) {
4971 ALOGV("update routing change");
4972 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4973 adev->perf_lock_opts,
4974 adev->perf_lock_opts_size);
4975 if (adev->adm_on_routing_change)
4976 adev->adm_on_routing_change(adev->adm_data,
4977 out->handle);
4978 }
4979 if (!bypass_a2dp) {
4980 select_devices(adev, out->usecase);
4981 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004982 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4983 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004984 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004985 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004987 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004988 }
4989
4990 if (!same_dev) {
4991 // on device switch force swap, lower functions will make sure
4992 // to check if swap is allowed or not.
4993 platform_set_swap_channels(adev, true);
4994 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4995 }
4996 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4997 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004998 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004999 pthread_mutex_lock(&out->compr_mute_lock);
5000 out->a2dp_compress_mute = false;
5001 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5002 pthread_mutex_unlock(&out->compr_mute_lock);
5003 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5004 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5005 }
5006 }
5007 }
5008
5009 pthread_mutex_unlock(&adev->lock);
5010 pthread_mutex_unlock(&out->lock);
5011
5012 /*handles device and call state changes*/
5013 audio_extn_extspk_update(adev->extspk);
5014
5015error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005016 ALOGV("%s: exit: code(%d)", __func__, ret);
5017 return ret;
5018}
5019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005020static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5021{
5022 struct stream_out *out = (struct stream_out *)stream;
5023 struct audio_device *adev = out->dev;
5024 struct str_parms *parms;
5025 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005026 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005027 int ext_controller = -1;
5028 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005029
sangwoobc677242013-08-08 16:53:43 +09005030 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005031 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305033 if (!parms)
5034 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005035
5036 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5037 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005038 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005039 out->extconn.cs.controller = ext_controller;
5040 out->extconn.cs.stream = ext_stream;
5041 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5042 use_case_table[out->usecase], out->extconn.cs.controller,
5043 out->extconn.cs.stream);
5044 }
5045
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005046 if (out == adev->primary_output) {
5047 pthread_mutex_lock(&adev->lock);
5048 audio_extn_set_parameters(adev, parms);
5049 pthread_mutex_unlock(&adev->lock);
5050 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005051 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005052 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005053 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005054
5055 audio_extn_dts_create_state_notifier_node(out->usecase);
5056 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5057 popcount(out->channel_mask),
5058 out->playback_started);
5059
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005060 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005061 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005062
Surendar Karkaf51b5842018-04-26 11:28:38 +05305063 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5064 sizeof(value));
5065 if (err >= 0) {
5066 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5067 audio_extn_send_dual_mono_mixing_coefficients(out);
5068 }
5069
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305070 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5071 if (err >= 0) {
5072 strlcpy(out->profile, value, sizeof(out->profile));
5073 ALOGV("updating stream profile with value '%s'", out->profile);
5074 lock_output_stream(out);
5075 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5076 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005077 &out->device_list, out->flags,
5078 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305079 out->sample_rate, out->bit_width,
5080 out->channel_mask, out->profile,
5081 &out->app_type_cfg);
5082 pthread_mutex_unlock(&out->lock);
5083 }
5084
Alexy Joseph98988832017-01-13 14:56:59 -08005085 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005086 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5087 // and vendor.audio.hal.output.suspend.supported is set to true
5088 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005089 //check suspend parameter only for low latency and if the property
5090 //is enabled
5091 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5092 ALOGI("%s: got suspend_playback %s", __func__, value);
5093 lock_output_stream(out);
5094 if (!strncmp(value, "false", 5)) {
5095 //suspend_playback=false is supposed to set QOS value back to 75%
5096 //the mixer control sent with value Enable will achieve that
5097 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5098 } else if (!strncmp (value, "true", 4)) {
5099 //suspend_playback=true is supposed to remove QOS value
5100 //resetting the mixer control will set the default value
5101 //for the mixer control which is Disable and this removes the QOS vote
5102 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5103 } else {
5104 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5105 " got %s", __func__, value);
5106 ret = -1;
5107 }
5108
5109 if (ret != 0) {
5110 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5111 __func__, out->pm_qos_mixer_path, ret);
5112 }
5113
5114 pthread_mutex_unlock(&out->lock);
5115 }
5116 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005117
Alexy Joseph98988832017-01-13 14:56:59 -08005118 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005119 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305120error:
Eric Laurent994a6932013-07-17 11:51:42 -07005121 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005122 return ret;
5123}
5124
Paul McLeana50b7332018-12-17 08:24:21 -07005125static int in_set_microphone_direction(const struct audio_stream_in *stream,
5126 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005127 struct stream_in *in = (struct stream_in *)stream;
5128
5129 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5130
5131 in->direction = dir;
5132
5133 if (in->standby)
5134 return 0;
5135
5136 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005137}
5138
5139static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005140 struct stream_in *in = (struct stream_in *)stream;
5141
5142 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5143
5144 if (zoom > 1.0 || zoom < -1.0)
5145 return -EINVAL;
5146
5147 in->zoom = zoom;
5148
5149 if (in->standby)
5150 return 0;
5151
5152 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005153}
5154
5155
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005156static bool stream_get_parameter_channels(struct str_parms *query,
5157 struct str_parms *reply,
5158 audio_channel_mask_t *supported_channel_masks) {
5159 int ret = -1;
5160 char value[512];
5161 bool first = true;
5162 size_t i, j;
5163
5164 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5165 ret = 0;
5166 value[0] = '\0';
5167 i = 0;
5168 while (supported_channel_masks[i] != 0) {
5169 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5170 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5171 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305172 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005173
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305174 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005175 first = false;
5176 break;
5177 }
5178 }
5179 i++;
5180 }
5181 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5182 }
5183 return ret == 0;
5184}
5185
5186static bool stream_get_parameter_formats(struct str_parms *query,
5187 struct str_parms *reply,
5188 audio_format_t *supported_formats) {
5189 int ret = -1;
5190 char value[256];
5191 size_t i, j;
5192 bool first = true;
5193
5194 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5195 ret = 0;
5196 value[0] = '\0';
5197 i = 0;
5198 while (supported_formats[i] != 0) {
5199 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5200 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5201 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305202 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005203 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305204 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005205 first = false;
5206 break;
5207 }
5208 }
5209 i++;
5210 }
5211 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5212 }
5213 return ret == 0;
5214}
5215
5216static bool stream_get_parameter_rates(struct str_parms *query,
5217 struct str_parms *reply,
5218 uint32_t *supported_sample_rates) {
5219
5220 int i;
5221 char value[256];
5222 int ret = -1;
5223 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5224 ret = 0;
5225 value[0] = '\0';
5226 i=0;
5227 int cursor = 0;
5228 while (supported_sample_rates[i]) {
5229 int avail = sizeof(value) - cursor;
5230 ret = snprintf(value + cursor, avail, "%s%d",
5231 cursor > 0 ? "|" : "",
5232 supported_sample_rates[i]);
5233 if (ret < 0 || ret >= avail) {
5234 // if cursor is at the last element of the array
5235 // overwrite with \0 is duplicate work as
5236 // snprintf already put a \0 in place.
5237 // else
5238 // we had space to write the '|' at value[cursor]
5239 // (which will be overwritten) or no space to fill
5240 // the first element (=> cursor == 0)
5241 value[cursor] = '\0';
5242 break;
5243 }
5244 cursor += ret;
5245 ++i;
5246 }
5247 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5248 value);
5249 }
5250 return ret >= 0;
5251}
5252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5254{
5255 struct stream_out *out = (struct stream_out *)stream;
5256 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005257 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258 char value[256];
5259 struct str_parms *reply = str_parms_create();
5260 size_t i, j;
5261 int ret;
5262 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005263
5264 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005265 if (reply) {
5266 str_parms_destroy(reply);
5267 }
5268 if (query) {
5269 str_parms_destroy(query);
5270 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005271 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5272 return NULL;
5273 }
5274
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005275 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005276 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5277 if (ret >= 0) {
5278 value[0] = '\0';
5279 i = 0;
5280 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005281 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5282 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005283 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005284 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005285 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005286 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005287 first = false;
5288 break;
5289 }
5290 }
5291 i++;
5292 }
5293 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5294 str = str_parms_to_str(reply);
5295 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005296 voice_extn_out_get_parameters(out, query, reply);
5297 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005298 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005299
Alexy Joseph62142aa2015-11-16 15:10:34 -08005300
5301 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5302 if (ret >= 0) {
5303 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305304 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5305 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005306 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305307 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005308 } else {
5309 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305310 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005311 }
5312 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005313 if (str)
5314 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005315 str = str_parms_to_str(reply);
5316 }
5317
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005318 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5319 if (ret >= 0) {
5320 value[0] = '\0';
5321 i = 0;
5322 first = true;
5323 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005324 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5325 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005326 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005327 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005328 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005329 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005330 first = false;
5331 break;
5332 }
5333 }
5334 i++;
5335 }
5336 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005337 if (str)
5338 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005339 str = str_parms_to_str(reply);
5340 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005341
5342 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5343 if (ret >= 0) {
5344 value[0] = '\0';
5345 i = 0;
5346 first = true;
5347 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005348 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5349 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005350 if (!first) {
5351 strlcat(value, "|", sizeof(value));
5352 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005353 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005354 first = false;
5355 break;
5356 }
5357 }
5358 i++;
5359 }
5360 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5361 if (str)
5362 free(str);
5363 str = str_parms_to_str(reply);
5364 }
5365
Alexy Joseph98988832017-01-13 14:56:59 -08005366 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5367 //only low latency track supports suspend_resume
5368 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005369 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005370 if (str)
5371 free(str);
5372 str = str_parms_to_str(reply);
5373 }
5374
5375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376 str_parms_destroy(query);
5377 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005378 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379 return str;
5380}
5381
5382static uint32_t out_get_latency(const struct audio_stream_out *stream)
5383{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005384 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005385 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005386 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387
Alexy Josephaa54c872014-12-03 02:46:47 -08005388 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305389 lock_output_stream(out);
5390 latency = audio_extn_utils_compress_get_dsp_latency(out);
5391 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005392 } else if ((out->realtime) ||
5393 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005394 // since the buffer won't be filled up faster than realtime,
5395 // return a smaller number
5396 if (out->config.rate)
5397 period_ms = (out->af_period_multiplier * out->config.period_size *
5398 1000) / (out->config.rate);
5399 else
5400 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005401 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005402 } else {
5403 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005404 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005405 }
5406
Zhou Songd2537a02020-06-11 22:04:46 +08005407 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005408 latency += audio_extn_a2dp_get_encoder_latency();
5409
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305410 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005411 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005412}
5413
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305414static float AmpToDb(float amplification)
5415{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305416 float db = DSD_VOLUME_MIN_DB;
5417 if (amplification > 0) {
5418 db = 20 * log10(amplification);
5419 if(db < DSD_VOLUME_MIN_DB)
5420 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305421 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305422 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305423}
5424
Arun Mirpuri5d170872019-03-26 13:21:31 -07005425static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5426 float right)
5427{
5428 struct stream_out *out = (struct stream_out *)stream;
5429 long volume = 0;
5430 char mixer_ctl_name[128] = "";
5431 struct audio_device *adev = out->dev;
5432 struct mixer_ctl *ctl = NULL;
5433 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5434 PCM_PLAYBACK);
5435
5436 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5437 "Playback %d Volume", pcm_device_id);
5438 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5439 if (!ctl) {
5440 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5441 __func__, mixer_ctl_name);
5442 return -EINVAL;
5443 }
5444 if (left != right)
5445 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5446 __func__, left, right);
5447 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5448 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5449 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5450 __func__, mixer_ctl_name, volume);
5451 return -EINVAL;
5452 }
5453 return 0;
5454}
5455
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305456static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5457 float right)
5458{
5459 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305460 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305461 char mixer_ctl_name[128];
5462 struct audio_device *adev = out->dev;
5463 struct mixer_ctl *ctl;
5464 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5465 PCM_PLAYBACK);
5466
5467 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5468 "Compress Playback %d Volume", pcm_device_id);
5469 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5470 if (!ctl) {
5471 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5472 __func__, mixer_ctl_name);
5473 return -EINVAL;
5474 }
5475 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5476 __func__, mixer_ctl_name, left, right);
5477 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5478 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5479 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5480
5481 return 0;
5482}
5483
Zhou Song2b8f28f2017-09-11 10:51:38 +08005484static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5485 float right)
5486{
5487 struct stream_out *out = (struct stream_out *)stream;
5488 char mixer_ctl_name[] = "App Type Gain";
5489 struct audio_device *adev = out->dev;
5490 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305491 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005492
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005493 if (!is_valid_volume(left, right)) {
5494 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5495 __func__, left, right);
5496 return -EINVAL;
5497 }
5498
Zhou Song2b8f28f2017-09-11 10:51:38 +08005499 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5500 if (!ctl) {
5501 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5502 __func__, mixer_ctl_name);
5503 return -EINVAL;
5504 }
5505
5506 set_values[0] = 0; //0: Rx Session 1:Tx Session
5507 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305508 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5509 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005510
5511 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5512 return 0;
5513}
5514
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305515static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5516 float right)
5517{
5518 struct stream_out *out = (struct stream_out *)stream;
5519 /* Volume control for pcm playback */
5520 if (left != right) {
5521 return -EINVAL;
5522 } else {
5523 char mixer_ctl_name[128];
5524 struct audio_device *adev = out->dev;
5525 struct mixer_ctl *ctl;
5526 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5527 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5528 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5529 if (!ctl) {
5530 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5531 return -EINVAL;
5532 }
5533
5534 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5535 int ret = mixer_ctl_set_value(ctl, 0, volume);
5536 if (ret < 0) {
5537 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5538 return -EINVAL;
5539 }
5540
5541 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5542
5543 return 0;
5544 }
5545}
5546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547static int out_set_volume(struct audio_stream_out *stream, float left,
5548 float right)
5549{
Eric Laurenta9024de2013-04-04 09:19:12 -07005550 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005551 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305552 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005553
Arun Mirpuri5d170872019-03-26 13:21:31 -07005554 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005555 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5556 /* only take left channel into account: the API is for stereo anyway */
5557 out->muted = (left == 0.0f);
5558 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005559 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305560 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005561 /*
5562 * Set mute or umute on HDMI passthrough stream.
5563 * Only take left channel into account.
5564 * Mute is 0 and unmute 1
5565 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305566 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305567 } else if (out->format == AUDIO_FORMAT_DSD){
5568 char mixer_ctl_name[128] = "DSD Volume";
5569 struct audio_device *adev = out->dev;
5570 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5571
5572 if (!ctl) {
5573 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5574 __func__, mixer_ctl_name);
5575 return -EINVAL;
5576 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305577 volume[0] = (long)(AmpToDb(left));
5578 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305579 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5580 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005581 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005582 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005583 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5584 struct listnode *node = NULL;
5585 list_for_each(node, &adev->active_outputs_list) {
5586 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5587 streams_output_ctxt_t,
5588 list);
5589 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5590 out->volume_l = out_ctxt->output->volume_l;
5591 out->volume_r = out_ctxt->output->volume_r;
5592 }
5593 }
5594 if (!out->a2dp_compress_mute) {
5595 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5596 }
5597 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005598 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305599 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005600 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305601 if (!out->a2dp_compress_mute)
5602 ret = out_set_compr_volume(stream, left, right);
5603 out->volume_l = left;
5604 out->volume_r = right;
5605 pthread_mutex_unlock(&out->compr_mute_lock);
5606 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005607 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005608 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005609 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5610 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5611 if (!out->standby) {
5612 audio_extn_utils_send_app_type_gain(out->dev,
5613 out->app_type_cfg.app_type,
5614 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005615 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005616 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005617 out->volume_l = left;
5618 out->volume_r = right;
5619 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005620 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5621 ALOGV("%s: MMAP set volume called", __func__);
5622 if (!out->standby)
5623 ret = out_set_mmap_volume(stream, left, right);
5624 out->volume_l = left;
5625 out->volume_r = right;
5626 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305627 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305628 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5629 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305630 /* Volume control for pcm playback */
5631 if (!out->standby)
5632 ret = out_set_pcm_volume(stream, left, right);
5633 else
5634 out->apply_volume = true;
5635
5636 out->volume_l = left;
5637 out->volume_r = right;
5638 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005639 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5640 ALOGV("%s: bus device set volume called", __func__);
5641 if (!out->standby)
5642 ret = out_set_pcm_volume(stream, left, right);
5643 out->volume_l = left;
5644 out->volume_r = right;
5645 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005646 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005648 return -ENOSYS;
5649}
5650
Zhou Songc9672822017-08-16 16:01:39 +08005651static void update_frames_written(struct stream_out *out, size_t bytes)
5652{
5653 size_t bpf = 0;
5654
5655 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5656 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5657 bpf = 1;
5658 else if (!is_offload_usecase(out->usecase))
5659 bpf = audio_bytes_per_sample(out->format) *
5660 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005661
5662 pthread_mutex_lock(&out->position_query_lock);
5663 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005664 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005665 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5666 }
5667 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005668}
5669
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005670int split_and_write_audio_haptic_data(struct stream_out *out,
5671 const void *buffer, size_t bytes_to_write)
5672{
5673 struct audio_device *adev = out->dev;
5674
5675 int ret = 0;
5676 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5677 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5678 size_t frame_size = channel_count * bytes_per_sample;
5679 size_t frame_count = bytes_to_write / frame_size;
5680
5681 bool force_haptic_path =
5682 property_get_bool("vendor.audio.test_haptic", false);
5683
5684 // extract Haptics data from Audio buffer
5685 bool alloc_haptic_buffer = false;
5686 int haptic_channel_count = adev->haptics_config.channels;
5687 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5688 size_t audio_frame_size = frame_size - haptic_frame_size;
5689 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5690
5691 if (adev->haptic_buffer == NULL) {
5692 alloc_haptic_buffer = true;
5693 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5694 free(adev->haptic_buffer);
5695 adev->haptic_buffer_size = 0;
5696 alloc_haptic_buffer = true;
5697 }
5698
5699 if (alloc_haptic_buffer) {
5700 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005701 if(adev->haptic_buffer == NULL) {
5702 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5703 return -ENOMEM;
5704 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005705 adev->haptic_buffer_size = total_haptic_buffer_size;
5706 }
5707
5708 size_t src_index = 0, aud_index = 0, hap_index = 0;
5709 uint8_t *audio_buffer = (uint8_t *)buffer;
5710 uint8_t *haptic_buffer = adev->haptic_buffer;
5711
5712 // This is required for testing only. This works for stereo data only.
5713 // One channel is fed to audio stream and other to haptic stream for testing.
5714 if (force_haptic_path)
5715 audio_frame_size = haptic_frame_size = bytes_per_sample;
5716
5717 for (size_t i = 0; i < frame_count; i++) {
5718 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5719 audio_frame_size);
5720 aud_index += audio_frame_size;
5721 src_index += audio_frame_size;
5722
5723 if (adev->haptic_pcm)
5724 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5725 haptic_frame_size);
5726 hap_index += haptic_frame_size;
5727 src_index += haptic_frame_size;
5728
5729 // This is required for testing only.
5730 // Discard haptic channel data.
5731 if (force_haptic_path)
5732 src_index += haptic_frame_size;
5733 }
5734
5735 // write to audio pipeline
5736 ret = pcm_write(out->pcm, (void *)audio_buffer,
5737 frame_count * audio_frame_size);
5738
5739 // write to haptics pipeline
5740 if (adev->haptic_pcm)
5741 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5742 frame_count * haptic_frame_size);
5743
5744 return ret;
5745}
5746
Aalique Grahame22e49102018-12-18 14:23:57 -08005747#ifdef NO_AUDIO_OUT
5748static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5749 const void *buffer __unused, size_t bytes)
5750{
5751 struct stream_out *out = (struct stream_out *)stream;
5752
5753 /* No Output device supported other than BT for playback.
5754 * Sleep for the amount of buffer duration
5755 */
5756 lock_output_stream(out);
5757 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5758 (const struct audio_stream_out *)&out->stream) /
5759 out_get_sample_rate(&out->stream.common));
5760 pthread_mutex_unlock(&out->lock);
5761 return bytes;
5762}
5763#endif
5764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5766 size_t bytes)
5767{
5768 struct stream_out *out = (struct stream_out *)stream;
5769 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005770 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305771 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005772 const size_t frame_size = audio_stream_out_frame_size(stream);
5773 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305774 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005775 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776
Haynes Mathew George380745d2017-10-04 15:27:45 -07005777 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005778 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305779
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305780 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005781
Dhananjay Kumarac341582017-02-23 23:42:25 +05305782 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305783 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305784 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5785 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005786 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305787 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305788 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305789 ALOGD(" %s: sound card is not active/SSR state", __func__);
5790 ret= -EIO;
5791 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305792 }
5793 }
5794
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305795 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305796 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305797 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305798 goto exit;
5799 }
5800
Haynes Mathew George16081042017-05-31 17:16:49 -07005801 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5802 ret = -EINVAL;
5803 goto exit;
5804 }
5805
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005806 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305807 !out->is_iec61937_info_available) {
5808
5809 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5810 out->is_iec61937_info_available = true;
5811 } else if (audio_extn_passthru_is_enabled()) {
5812 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305813 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305814
5815 if((out->format == AUDIO_FORMAT_DTS) ||
5816 (out->format == AUDIO_FORMAT_DTS_HD)) {
5817 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5818 buffer, bytes);
5819 if (ret) {
5820 if (ret != -ENOSYS) {
5821 out->is_iec61937_info_available = false;
5822 ALOGD("iec61937 transmission info not yet updated retry");
5823 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305824 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305825 /* if stream has started and after that there is
5826 * stream config change (iec transmission config)
5827 * then trigger select_device to update backend configuration.
5828 */
5829 out->stream_config_changed = true;
5830 pthread_mutex_lock(&adev->lock);
5831 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305832 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005833 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305834 ret = -EINVAL;
5835 goto exit;
5836 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305837 pthread_mutex_unlock(&adev->lock);
5838 out->stream_config_changed = false;
5839 out->is_iec61937_info_available = true;
5840 }
5841 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305842
Meng Wang4c32fb42020-01-16 17:57:11 +08005843#ifdef AUDIO_GKI_ENABLED
5844 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5845 compr_passthr = out->compr_config.codec->reserved[0];
5846#else
5847 compr_passthr = out->compr_config.codec->compr_passthr;
5848#endif
5849
Garmond Leung317cbf12017-09-13 16:20:50 -07005850 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005851 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305852 (out->is_iec61937_info_available == true)) {
5853 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5854 ret = -EINVAL;
5855 goto exit;
5856 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305857 }
5858 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305859
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005860 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005861 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005862 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5863 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305864 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305865 ret = -EIO;
5866 goto exit;
5867 }
5868 }
5869 }
5870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005871 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005872 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005873 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5874
Eric Laurent150dbfe2013-02-27 14:31:02 -08005875 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005876 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5877 ret = voice_extn_compress_voip_start_output_stream(out);
5878 else
5879 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005880 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005881 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005882 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005883 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005884 goto exit;
5885 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305886 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005887 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005888
5889 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005890 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005891 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305892 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005893 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005894 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305895
5896 if ((out->is_iec61937_info_available == true) &&
5897 (audio_extn_passthru_is_passthrough_stream(out))&&
5898 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5899 ret = -EINVAL;
5900 goto exit;
5901 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305902 if (out->set_dual_mono)
5903 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005904
5905 // log startup time in ms.
5906 simple_stats_log(
5907 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005908 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005909
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005910 if (adev->is_channel_status_set == false &&
5911 compare_device_type(&out->device_list,
5912 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005913 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305914 adev->is_channel_status_set = true;
5915 }
5916
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305917 if ((adev->use_old_pspd_mix_ctrl == true) &&
5918 (out->pspd_coeff_sent == false)) {
5919 /*
5920 * Need to resend pspd coefficients after stream started for
5921 * older kernel version as it does not save the coefficients
5922 * and also stream has to be started for coeff to apply.
5923 */
5924 usecase = get_usecase_from_list(adev, out->usecase);
5925 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305926 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305927 out->pspd_coeff_sent = true;
5928 }
5929 }
5930
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005931 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005932 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005933 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005934 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005935 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5936 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305937 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5938 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005939 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305940 out->send_next_track_params = false;
5941 out->is_compr_metadata_avail = false;
5942 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005943 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305944 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305945 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005946
Ashish Jain83a6cc22016-06-28 14:34:17 +05305947 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305948 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305949 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305950 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005951 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305952 return -EINVAL;
5953 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305954 audio_format_t dst_format = out->hal_op_format;
5955 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305956
Dieter Luecking5d57def2018-09-07 14:23:37 +02005957 /* prevent division-by-zero */
5958 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5959 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5960 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5961 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305962 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005963 ATRACE_END();
5964 return -EINVAL;
5965 }
5966
Ashish Jainf1eaa582016-05-23 20:54:24 +05305967 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5968 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5969
Ashish Jain83a6cc22016-06-28 14:34:17 +05305970 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305971 dst_format,
5972 buffer,
5973 src_format,
5974 frames);
5975
Ashish Jain83a6cc22016-06-28 14:34:17 +05305976 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305977 bytes_to_write);
5978
5979 /*Convert written bytes in audio flinger format*/
5980 if (ret > 0)
5981 ret = ((ret * format_to_bitwidth_table[out->format]) /
5982 format_to_bitwidth_table[dst_format]);
5983 }
5984 } else
5985 ret = compress_write(out->compr, buffer, bytes);
5986
Zhou Songc9672822017-08-16 16:01:39 +08005987 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5988 update_frames_written(out, bytes);
5989
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305990 if (ret < 0)
5991 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005992 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305993 /*msg to cb thread only if non blocking write is enabled*/
5994 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305995 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005996 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305997 } else if (-ENETRESET == ret) {
5998 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305999 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306000 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306001 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006002 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306003 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006004 }
Ashish Jain5106d362016-05-11 19:23:33 +05306005
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306006 /* Call compr start only when non-zero bytes of data is there to be rendered */
6007 if (!out->playback_started && ret > 0) {
6008 int status = compress_start(out->compr);
6009 if (status < 0) {
6010 ret = status;
6011 ALOGE("%s: compr start failed with err %d", __func__, errno);
6012 goto exit;
6013 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006014 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 out->playback_started = 1;
6016 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006017
6018 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6019 popcount(out->channel_mask),
6020 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006021 }
6022 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006023 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006024 return ret;
6025 } else {
6026 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006027 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006028 if (out->muted)
6029 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006030 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6031 __func__, frames, frame_size, bytes_to_write);
6032
Aalique Grahame22e49102018-12-18 14:23:57 -08006033 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006034 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6035 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6036 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006037 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6038 int16_t *src = (int16_t *)buffer;
6039 int16_t *dst = (int16_t *)buffer;
6040
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006041 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006042 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006043 "out_write called for %s use case with wrong properties",
6044 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006045
6046 /*
6047 * FIXME: this can be removed once audio flinger mixer supports
6048 * mono output
6049 */
6050
6051 /*
6052 * Code below goes over each frame in the buffer and adds both
6053 * L and R samples and then divides by 2 to convert to mono
6054 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006055 if (channel_count == 2) {
6056 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6057 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6058 }
6059 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006060 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006061 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006062
6063 // Note: since out_get_presentation_position() is called alternating with out_write()
6064 // by AudioFlinger, we can check underruns using the prior timestamp read.
6065 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6066 if (out->last_fifo_valid) {
6067 // compute drain to see if there is an underrun.
6068 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306069 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6070 int64_t frames_by_time =
6071 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6072 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006073 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6074
6075 if (underrun > 0) {
6076 simple_stats_log(&out->fifo_underruns, underrun);
6077
6078 ALOGW("%s: underrun(%lld) "
6079 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6080 __func__,
6081 (long long)out->fifo_underruns.n,
6082 (long long)frames_by_time,
6083 (long long)out->last_fifo_frames_remaining);
6084 }
6085 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6086 }
6087
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306088 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006089
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006090 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006091
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006092 if (out->config.rate)
6093 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6094 out->config.rate;
6095
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006096 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006097 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6098
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006099 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006100 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006101 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306102 out->convert_buffer != NULL) {
6103
6104 memcpy_by_audio_format(out->convert_buffer,
6105 out->hal_op_format,
6106 buffer,
6107 out->hal_ip_format,
6108 out->config.period_size * out->config.channels);
6109
6110 ret = pcm_write(out->pcm, out->convert_buffer,
6111 (out->config.period_size *
6112 out->config.channels *
6113 format_to_bitwidth_table[out->hal_op_format]));
6114 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306115 /*
6116 * To avoid underrun in DSP when the application is not pumping
6117 * data at required rate, check for the no. of bytes and ignore
6118 * pcm_write if it is less than actual buffer size.
6119 * It is a work around to a change in compress VOIP driver.
6120 */
6121 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6122 bytes < (out->config.period_size * out->config.channels *
6123 audio_bytes_per_sample(out->format))) {
6124 size_t voip_buf_size =
6125 out->config.period_size * out->config.channels *
6126 audio_bytes_per_sample(out->format);
6127 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6128 __func__, bytes, voip_buf_size);
6129 usleep(((uint64_t)voip_buf_size - bytes) *
6130 1000000 / audio_stream_out_frame_size(stream) /
6131 out_get_sample_rate(&out->stream.common));
6132 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006133 } else {
6134 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6135 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6136 else
6137 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6138 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306139 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006140
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006141 release_out_focus(out);
6142
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306143 if (ret < 0)
6144 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006145 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306146 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006147 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006148 }
6149
6150exit:
Zhou Songc9672822017-08-16 16:01:39 +08006151 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306152 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306153 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155 pthread_mutex_unlock(&out->lock);
6156
6157 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006158 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006159 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306160 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306161 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306162 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306163 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306164 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306165 out->standby = true;
6166 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306167 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006168 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6169 /* prevent division-by-zero */
6170 uint32_t stream_size = audio_stream_out_frame_size(stream);
6171 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006172
Dieter Luecking5d57def2018-09-07 14:23:37 +02006173 if ((stream_size == 0) || (srate == 0)) {
6174 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6175 ATRACE_END();
6176 return -EINVAL;
6177 }
6178 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6179 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006180 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306181 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006182 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006183 return ret;
6184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006185 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006186 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006187 return bytes;
6188}
6189
6190static int out_get_render_position(const struct audio_stream_out *stream,
6191 uint32_t *dsp_frames)
6192{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006193 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006194
6195 if (dsp_frames == NULL)
6196 return -EINVAL;
6197
6198 *dsp_frames = 0;
6199 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006200 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306201
6202 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6203 * this operation and adev_close_output_stream(where out gets reset).
6204 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306205 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006206 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306207 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006208 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306209 return 0;
6210 }
6211
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006212 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306213 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306214 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006215 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306216 if (ret < 0)
6217 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006218 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306219 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006220 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306221 if (-ENETRESET == ret) {
6222 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306223 out->card_status = CARD_STATUS_OFFLINE;
6224 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306225 } else if(ret < 0) {
6226 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306227 ret = -EINVAL;
6228 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306229 /*
6230 * Handle corner case where compress session is closed during SSR
6231 * and timestamp is queried
6232 */
6233 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306234 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306235 } else if (out->prev_card_status_offline) {
6236 ALOGE("ERROR: previously sound card was offline,return error");
6237 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306238 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306239 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006240 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306241 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306242 pthread_mutex_unlock(&out->lock);
6243 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006244 } else if (audio_is_linear_pcm(out->format)) {
6245 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006246 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006247 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006248 } else
6249 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006250}
6251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006252static int out_add_audio_effect(const struct audio_stream *stream __unused,
6253 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006254{
6255 return 0;
6256}
6257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006258static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6259 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006260{
6261 return 0;
6262}
6263
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006264static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6265 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306267 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268}
6269
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006270static int out_get_presentation_position(const struct audio_stream_out *stream,
6271 uint64_t *frames, struct timespec *timestamp)
6272{
6273 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306274 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006275 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006276
Ashish Jain5106d362016-05-11 19:23:33 +05306277 /* below piece of code is not guarded against any lock because audioFliner serializes
6278 * this operation and adev_close_output_stream( where out gets reset).
6279 */
6280 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306281 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006282 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306283 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6284 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6285 return 0;
6286 }
6287
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006288 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006289
Ashish Jain5106d362016-05-11 19:23:33 +05306290 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6291 ret = compress_get_tstamp(out->compr, &dsp_frames,
6292 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006293 // Adjustment accounts for A2dp encoder latency with offload usecases
6294 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006295 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006296 unsigned long offset =
6297 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6298 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6299 }
Ashish Jain5106d362016-05-11 19:23:33 +05306300 ALOGVV("%s rendered frames %ld sample_rate %d",
6301 __func__, dsp_frames, out->sample_rate);
6302 *frames = dsp_frames;
6303 if (ret < 0)
6304 ret = -errno;
6305 if (-ENETRESET == ret) {
6306 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306307 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306308 ret = -EINVAL;
6309 } else
6310 ret = 0;
6311 /* this is the best we can do */
6312 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006313 } else {
6314 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006315 unsigned int avail;
6316 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006317 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006318 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006319
Andy Hunga1f48fa2019-07-01 18:14:53 -07006320 if (out->kernel_buffer_size > avail) {
6321 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6322 } else {
6323 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6324 __func__, avail, out->kernel_buffer_size);
6325 avail = out->kernel_buffer_size;
6326 frames_temp = out->last_fifo_frames_remaining = 0;
6327 }
6328 out->last_fifo_valid = true;
6329 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6330
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006331 if (out->written >= frames_temp)
6332 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006333
Andy Hunga1f48fa2019-07-01 18:14:53 -07006334 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6335 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6336
Weiyin Jiangd4633762018-03-16 12:05:03 +08006337 // This adjustment accounts for buffering after app processor.
6338 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006339 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006340 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006341 if (signed_frames >= frames_temp)
6342 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006343
Weiyin Jiangd4633762018-03-16 12:05:03 +08006344 // Adjustment accounts for A2dp encoder latency with non offload usecases
6345 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006346 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006347 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6348 if (signed_frames >= frames_temp)
6349 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006350 }
6351
6352 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006353 *frames = signed_frames;
6354 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006355 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006356 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6357 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006358 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306359 *frames = out->written;
6360 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306361 if (is_offload_usecase(out->usecase))
6362 ret = -EINVAL;
6363 else
6364 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006365 }
6366 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006367 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006368 return ret;
6369}
6370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006371static int out_set_callback(struct audio_stream_out *stream,
6372 stream_callback_t callback, void *cookie)
6373{
6374 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006375 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006376
6377 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006378 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006379 out->client_callback = callback;
6380 out->client_cookie = cookie;
6381 if (out->adsp_hdlr_stream_handle) {
6382 ret = audio_extn_adsp_hdlr_stream_set_callback(
6383 out->adsp_hdlr_stream_handle,
6384 callback,
6385 cookie);
6386 if (ret)
6387 ALOGW("%s:adsp hdlr callback registration failed %d",
6388 __func__, ret);
6389 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006390 pthread_mutex_unlock(&out->lock);
6391 return 0;
6392}
6393
6394static int out_pause(struct audio_stream_out* stream)
6395{
6396 struct stream_out *out = (struct stream_out *)stream;
6397 int status = -ENOSYS;
6398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006400 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306401 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006402 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306404 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306405 status = compress_pause(out->compr);
6406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006407 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006408
Mingming Yin21854652016-04-13 11:54:02 -07006409 if (audio_extn_passthru_is_active()) {
6410 ALOGV("offload use case, pause passthru");
6411 audio_extn_passthru_on_pause(out);
6412 }
6413
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306414 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006415 audio_extn_dts_notify_playback_state(out->usecase, 0,
6416 out->sample_rate, popcount(out->channel_mask),
6417 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006418 }
6419 pthread_mutex_unlock(&out->lock);
6420 }
6421 return status;
6422}
6423
6424static int out_resume(struct audio_stream_out* stream)
6425{
6426 struct stream_out *out = (struct stream_out *)stream;
6427 int status = -ENOSYS;
6428 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006429 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006430 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306431 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006432 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006433 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306434 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306435 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006436 }
6437 if (!status) {
6438 out->offload_state = OFFLOAD_STATE_PLAYING;
6439 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306440 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006441 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6442 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006443 }
6444 pthread_mutex_unlock(&out->lock);
6445 }
6446 return status;
6447}
6448
6449static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6450{
6451 struct stream_out *out = (struct stream_out *)stream;
6452 int status = -ENOSYS;
6453 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006454 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006455 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006456 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6457 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6458 else
6459 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6460 pthread_mutex_unlock(&out->lock);
6461 }
6462 return status;
6463}
6464
6465static int out_flush(struct audio_stream_out* stream)
6466{
6467 struct stream_out *out = (struct stream_out *)stream;
6468 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006469 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006470 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006471 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006472 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6473 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006474 } else {
6475 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6476 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006477 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006478 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006479 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006480 return 0;
6481 }
6482 return -ENOSYS;
6483}
6484
Haynes Mathew George16081042017-05-31 17:16:49 -07006485static int out_stop(const struct audio_stream_out* stream)
6486{
6487 struct stream_out *out = (struct stream_out *)stream;
6488 struct audio_device *adev = out->dev;
6489 int ret = -ENOSYS;
6490
6491 ALOGV("%s", __func__);
6492 pthread_mutex_lock(&adev->lock);
6493 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6494 out->playback_started && out->pcm != NULL) {
6495 pcm_stop(out->pcm);
6496 ret = stop_output_stream(out);
6497 out->playback_started = false;
6498 }
6499 pthread_mutex_unlock(&adev->lock);
6500 return ret;
6501}
6502
6503static int out_start(const struct audio_stream_out* stream)
6504{
6505 struct stream_out *out = (struct stream_out *)stream;
6506 struct audio_device *adev = out->dev;
6507 int ret = -ENOSYS;
6508
6509 ALOGV("%s", __func__);
6510 pthread_mutex_lock(&adev->lock);
6511 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6512 !out->playback_started && out->pcm != NULL) {
6513 ret = start_output_stream(out);
6514 if (ret == 0) {
6515 out->playback_started = true;
6516 }
6517 }
6518 pthread_mutex_unlock(&adev->lock);
6519 return ret;
6520}
6521
6522/*
6523 * Modify config->period_count based on min_size_frames
6524 */
6525static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6526{
6527 int periodCountRequested = (min_size_frames + config->period_size - 1)
6528 / config->period_size;
6529 int periodCount = MMAP_PERIOD_COUNT_MIN;
6530
6531 ALOGV("%s original config.period_size = %d config.period_count = %d",
6532 __func__, config->period_size, config->period_count);
6533
6534 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6535 periodCount *= 2;
6536 }
6537 config->period_count = periodCount;
6538
6539 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6540}
6541
Phil Burkfe17efd2019-03-25 10:23:35 -07006542// Read offset for the positional timestamp from a persistent vendor property.
6543// This is to workaround apparent inaccuracies in the timing information that
6544// is used by the AAudio timing model. The inaccuracies can cause glitches.
6545static int64_t get_mmap_out_time_offset() {
6546 const int32_t kDefaultOffsetMicros = 0;
6547 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006548 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006549 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6550 return mmap_time_offset_micros * (int64_t)1000;
6551}
6552
Haynes Mathew George16081042017-05-31 17:16:49 -07006553static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6554 int32_t min_size_frames,
6555 struct audio_mmap_buffer_info *info)
6556{
6557 struct stream_out *out = (struct stream_out *)stream;
6558 struct audio_device *adev = out->dev;
6559 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006560 unsigned int offset1 = 0;
6561 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006562 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006563 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006564 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006565
Arun Mirpuri5d170872019-03-26 13:21:31 -07006566 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306567 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006568 pthread_mutex_lock(&adev->lock);
6569
Sharad Sanglec6f32552018-05-04 16:15:38 +05306570 if (CARD_STATUS_OFFLINE == out->card_status ||
6571 CARD_STATUS_OFFLINE == adev->card_status) {
6572 ALOGW("out->card_status or adev->card_status offline, try again");
6573 ret = -EIO;
6574 goto exit;
6575 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306576 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006577 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6578 ret = -EINVAL;
6579 goto exit;
6580 }
6581 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6582 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6583 ret = -ENOSYS;
6584 goto exit;
6585 }
6586 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6587 if (out->pcm_device_id < 0) {
6588 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6589 __func__, out->pcm_device_id, out->usecase);
6590 ret = -EINVAL;
6591 goto exit;
6592 }
6593
6594 adjust_mmap_period_count(&out->config, min_size_frames);
6595
Arun Mirpuri5d170872019-03-26 13:21:31 -07006596 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006597 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6598 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6599 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306600 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306601 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6602 out->card_status = CARD_STATUS_OFFLINE;
6603 adev->card_status = CARD_STATUS_OFFLINE;
6604 ret = -EIO;
6605 goto exit;
6606 }
6607
Haynes Mathew George16081042017-05-31 17:16:49 -07006608 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6609 step = "open";
6610 ret = -ENODEV;
6611 goto exit;
6612 }
6613 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6614 if (ret < 0) {
6615 step = "begin";
6616 goto exit;
6617 }
juyuchen626833d2019-06-04 16:48:02 +08006618
6619 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006620 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006621 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006622 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006623 ret = platform_get_mmap_data_fd(adev->platform,
6624 out->pcm_device_id, 0 /*playback*/,
6625 &info->shared_memory_fd,
6626 &mmap_size);
6627 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006628 // Fall back to non exclusive mode
6629 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6630 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006631 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6632 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6633
Arun Mirpuri5d170872019-03-26 13:21:31 -07006634 if (mmap_size < buffer_size) {
6635 step = "mmap";
6636 goto exit;
6637 }
juyuchen626833d2019-06-04 16:48:02 +08006638 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006639 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006640 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006641 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006642
6643 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6644 if (ret < 0) {
6645 step = "commit";
6646 goto exit;
6647 }
6648
Phil Burkfe17efd2019-03-25 10:23:35 -07006649 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6650
Haynes Mathew George16081042017-05-31 17:16:49 -07006651 out->standby = false;
6652 ret = 0;
6653
Arun Mirpuri5d170872019-03-26 13:21:31 -07006654 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006655 __func__, info->shared_memory_address, info->buffer_size_frames);
6656
6657exit:
6658 if (ret != 0) {
6659 if (out->pcm == NULL) {
6660 ALOGE("%s: %s - %d", __func__, step, ret);
6661 } else {
6662 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6663 pcm_close(out->pcm);
6664 out->pcm = NULL;
6665 }
6666 }
6667 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306668 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006669 return ret;
6670}
6671
6672static int out_get_mmap_position(const struct audio_stream_out *stream,
6673 struct audio_mmap_position *position)
6674{
6675 struct stream_out *out = (struct stream_out *)stream;
6676 ALOGVV("%s", __func__);
6677 if (position == NULL) {
6678 return -EINVAL;
6679 }
6680 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006681 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006682 return -ENOSYS;
6683 }
6684 if (out->pcm == NULL) {
6685 return -ENOSYS;
6686 }
6687
6688 struct timespec ts = { 0, 0 };
6689 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6690 if (ret < 0) {
6691 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6692 return ret;
6693 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006694 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6695 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006696 return 0;
6697}
6698
6699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006700/** audio_stream_in implementation **/
6701static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6702{
6703 struct stream_in *in = (struct stream_in *)stream;
6704
6705 return in->config.rate;
6706}
6707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006708static int in_set_sample_rate(struct audio_stream *stream __unused,
6709 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006710{
6711 return -ENOSYS;
6712}
6713
6714static size_t in_get_buffer_size(const struct audio_stream *stream)
6715{
6716 struct stream_in *in = (struct stream_in *)stream;
6717
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006718 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6719 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006720 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6721 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306722 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306723 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006724
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006725 return in->config.period_size * in->af_period_multiplier *
6726 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727}
6728
6729static uint32_t in_get_channels(const struct audio_stream *stream)
6730{
6731 struct stream_in *in = (struct stream_in *)stream;
6732
6733 return in->channel_mask;
6734}
6735
6736static audio_format_t in_get_format(const struct audio_stream *stream)
6737{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006738 struct stream_in *in = (struct stream_in *)stream;
6739
6740 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006741}
6742
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006743static int in_set_format(struct audio_stream *stream __unused,
6744 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006745{
6746 return -ENOSYS;
6747}
6748
6749static int in_standby(struct audio_stream *stream)
6750{
6751 struct stream_in *in = (struct stream_in *)stream;
6752 struct audio_device *adev = in->dev;
6753 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306754 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6755 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006756 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306757
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006758 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006759 if (!in->standby && in->is_st_session) {
6760 ALOGD("%s: sound trigger pcm stop lab", __func__);
6761 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006762 if (adev->num_va_sessions > 0)
6763 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006764 in->standby = 1;
6765 }
6766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006767 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006768 if (adev->adm_deregister_stream)
6769 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6770
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006771 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006772 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006773 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006774 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006775 voice_extn_compress_voip_close_input_stream(stream);
6776 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006777 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6778 do_stop = in->capture_started;
6779 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006780 if (in->mmap_shared_memory_fd >= 0) {
6781 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6782 __func__, in->mmap_shared_memory_fd);
6783 close(in->mmap_shared_memory_fd);
6784 in->mmap_shared_memory_fd = -1;
6785 }
Zhou Songa8895042016-07-05 17:54:22 +08006786 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306787 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306788 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006789 }
6790
Arun Mirpuri5d170872019-03-26 13:21:31 -07006791 if (in->pcm) {
6792 ATRACE_BEGIN("pcm_in_close");
6793 pcm_close(in->pcm);
6794 ATRACE_END();
6795 in->pcm = NULL;
6796 }
6797
Carter Hsu2e429db2019-05-14 18:50:52 +08006798 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006799 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006800
George Gao3018ede2019-10-23 13:23:00 -07006801 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6802 if (adev->num_va_sessions > 0)
6803 adev->num_va_sessions--;
6804 }
Quinn Malef6050362019-01-30 15:55:40 -08006805
Eric Laurent150dbfe2013-02-27 14:31:02 -08006806 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006807 }
6808 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006809 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006810 return status;
6811}
6812
Aalique Grahame22e49102018-12-18 14:23:57 -08006813static int in_dump(const struct audio_stream *stream,
6814 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006815{
Aalique Grahame22e49102018-12-18 14:23:57 -08006816 struct stream_in *in = (struct stream_in *)stream;
6817
6818 // We try to get the lock for consistency,
6819 // but it isn't necessary for these variables.
6820 // If we're not in standby, we may be blocked on a read.
6821 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6822 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6823 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6824 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6825
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006826 char buffer[256]; // for statistics formatting
6827 if (in->start_latency_ms.n > 0) {
6828 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6829 dprintf(fd, " Start latency ms: %s\n", buffer);
6830 }
6831
Aalique Grahame22e49102018-12-18 14:23:57 -08006832 if (locked) {
6833 pthread_mutex_unlock(&in->lock);
6834 }
6835
6836 // dump error info
6837 (void)error_log_dump(
6838 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840 return 0;
6841}
6842
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306843static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6844{
6845 if (!stream || !parms)
6846 return;
6847
6848 struct stream_in *in = (struct stream_in *)stream;
6849 struct audio_device *adev = in->dev;
6850
6851 card_status_t status;
6852 int card;
6853 if (parse_snd_card_status(parms, &card, &status) < 0)
6854 return;
6855
6856 pthread_mutex_lock(&adev->lock);
6857 bool valid_cb = (card == adev->snd_card);
6858 pthread_mutex_unlock(&adev->lock);
6859
6860 if (!valid_cb)
6861 return;
6862
6863 lock_input_stream(in);
6864 if (in->card_status != status)
6865 in->card_status = status;
6866 pthread_mutex_unlock(&in->lock);
6867
6868 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6869 use_case_table[in->usecase],
6870 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6871
6872 // a better solution would be to report error back to AF and let
6873 // it put the stream to standby
6874 if (status == CARD_STATUS_OFFLINE)
6875 in_standby(&in->stream.common);
6876
6877 return;
6878}
6879
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006880int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006881 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006882 audio_source_t source)
6883{
6884 struct audio_device *adev = in->dev;
6885 int ret = 0;
6886
6887 lock_input_stream(in);
6888 pthread_mutex_lock(&adev->lock);
6889
6890 /* no audio source uses val == 0 */
6891 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6892 in->source = source;
6893 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6894 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6895 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6896 (in->config.rate == 8000 || in->config.rate == 16000 ||
6897 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6898 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6899 ret = voice_extn_compress_voip_open_input_stream(in);
6900 if (ret != 0) {
6901 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6902 __func__, ret);
6903 }
6904 }
6905 }
6906
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006907 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6908 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006909 // Workaround: If routing to an non existing usb device, fail gracefully
6910 // The routing request will otherwise block during 10 second
6911 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006912 struct str_parms *usb_addr =
6913 str_parms_create_str(get_usb_device_address(devices));
6914 if (is_usb_in_device_type(devices) && usb_addr &&
6915 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006916 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6917 ret = -ENOSYS;
6918 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006919 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006920 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006921 if (!in->standby && !in->is_st_session) {
6922 ALOGV("update input routing change");
6923 // inform adm before actual routing to prevent glitches.
6924 if (adev->adm_on_routing_change) {
6925 adev->adm_on_routing_change(adev->adm_data,
6926 in->capture_handle);
6927 ret = select_devices(adev, in->usecase);
6928 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6929 adev->adm_routing_changed = true;
6930 }
6931 }
6932 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006933 if (usb_addr)
6934 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006935 }
6936 pthread_mutex_unlock(&adev->lock);
6937 pthread_mutex_unlock(&in->lock);
6938
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07006939 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006940 return ret;
6941}
6942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6944{
6945 struct stream_in *in = (struct stream_in *)stream;
6946 struct audio_device *adev = in->dev;
6947 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006948 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306949 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006950
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306951 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006952 parms = str_parms_create_str(kvpairs);
6953
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306954 if (!parms)
6955 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006956 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006957 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006958
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306959 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6960 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306961 strlcpy(in->profile, value, sizeof(in->profile));
6962 ALOGV("updating stream profile with value '%s'", in->profile);
6963 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6964 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006965 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306966 in->sample_rate, in->bit_width,
6967 in->profile, &in->app_type_cfg);
6968 }
6969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006970 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006971 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006972
6973 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306974error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306975 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976}
6977
6978static char* in_get_parameters(const struct audio_stream *stream,
6979 const char *keys)
6980{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006981 struct stream_in *in = (struct stream_in *)stream;
6982 struct str_parms *query = str_parms_create_str(keys);
6983 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006984 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006985
6986 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006987 if (reply) {
6988 str_parms_destroy(reply);
6989 }
6990 if (query) {
6991 str_parms_destroy(query);
6992 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006993 ALOGE("in_get_parameters: failed to create query or reply");
6994 return NULL;
6995 }
6996
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006997 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006998
6999 voice_extn_in_get_parameters(in, query, reply);
7000
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007001 stream_get_parameter_channels(query, reply,
7002 &in->supported_channel_masks[0]);
7003 stream_get_parameter_formats(query, reply,
7004 &in->supported_formats[0]);
7005 stream_get_parameter_rates(query, reply,
7006 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007007 str = str_parms_to_str(reply);
7008 str_parms_destroy(query);
7009 str_parms_destroy(reply);
7010
7011 ALOGV("%s: exit: returns - %s", __func__, str);
7012 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007013}
7014
Aalique Grahame22e49102018-12-18 14:23:57 -08007015static int in_set_gain(struct audio_stream_in *stream,
7016 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007017{
Aalique Grahame22e49102018-12-18 14:23:57 -08007018 struct stream_in *in = (struct stream_in *)stream;
7019 char mixer_ctl_name[128];
7020 struct mixer_ctl *ctl;
7021 int ctl_value;
7022
7023 ALOGV("%s: gain %f", __func__, gain);
7024
7025 if (stream == NULL)
7026 return -EINVAL;
7027
7028 /* in_set_gain() only used to silence MMAP capture for now */
7029 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7030 return -ENOSYS;
7031
7032 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7033
7034 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7035 if (!ctl) {
7036 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7037 __func__, mixer_ctl_name);
7038 return -ENOSYS;
7039 }
7040
7041 if (gain < RECORD_GAIN_MIN)
7042 gain = RECORD_GAIN_MIN;
7043 else if (gain > RECORD_GAIN_MAX)
7044 gain = RECORD_GAIN_MAX;
7045 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7046
7047 mixer_ctl_set_value(ctl, 0, ctl_value);
7048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007049 return 0;
7050}
7051
7052static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7053 size_t bytes)
7054{
7055 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307056
7057 if (in == NULL) {
7058 ALOGE("%s: stream_in ptr is NULL", __func__);
7059 return -EINVAL;
7060 }
7061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307063 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307064 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007065
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007066 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307067
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007068 if (in->is_st_session) {
7069 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7070 /* Read from sound trigger HAL */
7071 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007072 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007073 if (adev->num_va_sessions < UINT_MAX)
7074 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007075 in->standby = 0;
7076 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007077 pthread_mutex_unlock(&in->lock);
7078 return bytes;
7079 }
7080
Haynes Mathew George16081042017-05-31 17:16:49 -07007081 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7082 ret = -ENOSYS;
7083 goto exit;
7084 }
7085
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007086 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7087 !in->standby && adev->adm_routing_changed) {
7088 ret = -ENOSYS;
7089 goto exit;
7090 }
7091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007093 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7094
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007095 pthread_mutex_lock(&adev->lock);
7096 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7097 ret = voice_extn_compress_voip_start_input_stream(in);
7098 else
7099 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007100 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7101 if (adev->num_va_sessions < UINT_MAX)
7102 adev->num_va_sessions++;
7103 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007104 pthread_mutex_unlock(&adev->lock);
7105 if (ret != 0) {
7106 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007107 }
7108 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007109
7110 // log startup time in ms.
7111 simple_stats_log(
7112 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007114
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307115 /* Avoid read if capture_stopped is set */
7116 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7117 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7118 ret = -EINVAL;
7119 goto exit;
7120 }
7121
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007122 // what's the duration requested by the client?
7123 long ns = 0;
7124
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307125 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007126 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7127 in->config.rate;
7128
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007129 ret = request_in_focus(in, ns);
7130 if (ret != 0)
7131 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007132 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007133
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307134 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307135 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7136 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307137 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007138 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307139 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007140 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007141 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007142 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007143 } else if (audio_extn_ffv_get_stream() == in) {
7144 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307145 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007146 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307147 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7148 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7149 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7150 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307151 ret = -EINVAL;
7152 goto exit;
7153 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307154 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307155 ret = -errno;
7156 }
7157 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307158 /* bytes read is always set to bytes for non compress usecases */
7159 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007160 }
7161
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007162 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007164 /*
Quinn Malef6050362019-01-30 15:55:40 -08007165 * Instead of writing zeroes here, we could trust the hardware to always
7166 * provide zeroes when muted. This is also muted with voice recognition
7167 * usecases so that other clients do not have access to voice recognition
7168 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007169 */
Quinn Malef6050362019-01-30 15:55:40 -08007170 if ((ret == 0 && voice_get_mic_mute(adev) &&
7171 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007172 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7173 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007174 (adev->num_va_sessions &&
7175 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7176 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7177 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007178 memset(buffer, 0, bytes);
7179
7180exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307181 frame_size = audio_stream_in_frame_size(stream);
7182 if (frame_size > 0)
7183 in->frames_read += bytes_read/frame_size;
7184
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007185 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307186 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187 pthread_mutex_unlock(&in->lock);
7188
7189 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307190 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307191 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307192 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307193 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307194 in->standby = true;
7195 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307196 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307197 bytes_read = bytes;
7198 memset(buffer, 0, bytes);
7199 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007200 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007201 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7202 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007203 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307204 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307205 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007206 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307207 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007208}
7209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007210static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007211{
7212 return 0;
7213}
7214
Aalique Grahame22e49102018-12-18 14:23:57 -08007215static int in_get_capture_position(const struct audio_stream_in *stream,
7216 int64_t *frames, int64_t *time)
7217{
7218 if (stream == NULL || frames == NULL || time == NULL) {
7219 return -EINVAL;
7220 }
7221 struct stream_in *in = (struct stream_in *)stream;
7222 int ret = -ENOSYS;
7223
7224 lock_input_stream(in);
7225 // note: ST sessions do not close the alsa pcm driver synchronously
7226 // on standby. Therefore, we may return an error even though the
7227 // pcm stream is still opened.
7228 if (in->standby) {
7229 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7230 "%s stream in standby but pcm not NULL for non ST session", __func__);
7231 goto exit;
7232 }
7233 if (in->pcm) {
7234 struct timespec timestamp;
7235 unsigned int avail;
7236 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7237 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007238 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007239 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007240 ret = 0;
7241 }
7242 }
7243exit:
7244 pthread_mutex_unlock(&in->lock);
7245 return ret;
7246}
7247
Carter Hsu2e429db2019-05-14 18:50:52 +08007248static int in_update_effect_list(bool add, effect_handle_t effect,
7249 struct listnode *head)
7250{
7251 struct listnode *node;
7252 struct in_effect_list *elist = NULL;
7253 struct in_effect_list *target = NULL;
7254 int ret = 0;
7255
7256 if (!head)
7257 return ret;
7258
7259 list_for_each(node, head) {
7260 elist = node_to_item(node, struct in_effect_list, list);
7261 if (elist->handle == effect) {
7262 target = elist;
7263 break;
7264 }
7265 }
7266
7267 if (add) {
7268 if (target) {
7269 ALOGD("effect %p already exist", effect);
7270 return ret;
7271 }
7272
7273 target = (struct in_effect_list *)
7274 calloc(1, sizeof(struct in_effect_list));
7275
7276 if (!target) {
7277 ALOGE("%s:fail to allocate memory", __func__);
7278 return -ENOMEM;
7279 }
7280
7281 target->handle = effect;
7282 list_add_tail(head, &target->list);
7283 } else {
7284 if (target) {
7285 list_remove(&target->list);
7286 free(target);
7287 }
7288 }
7289
7290 return ret;
7291}
7292
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007293static int add_remove_audio_effect(const struct audio_stream *stream,
7294 effect_handle_t effect,
7295 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007296{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007297 struct stream_in *in = (struct stream_in *)stream;
7298 int status = 0;
7299 effect_descriptor_t desc;
7300
7301 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007302 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7303
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007304 if (status != 0)
7305 return status;
7306
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007307 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007308 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007309 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007310 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7311 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007312 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007313
7314 in_update_effect_list(enable, effect, &in->aec_list);
7315 enable = !list_empty(&in->aec_list);
7316 if (enable == in->enable_aec)
7317 goto exit;
7318
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007319 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007320 ALOGD("AEC enable %d", enable);
7321
Aalique Grahame22e49102018-12-18 14:23:57 -08007322 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7323 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7324 in->dev->enable_voicerx = enable;
7325 struct audio_usecase *usecase;
7326 struct listnode *node;
7327 list_for_each(node, &in->dev->usecase_list) {
7328 usecase = node_to_item(node, struct audio_usecase, list);
7329 if (usecase->type == PCM_PLAYBACK)
7330 select_devices(in->dev, usecase->id);
7331 }
7332 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007333 if (!in->standby) {
7334 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7335 select_devices(in->dev, in->usecase);
7336 }
7337
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007338 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007339 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7340
7341 in_update_effect_list(enable, effect, &in->ns_list);
7342 enable = !list_empty(&in->ns_list);
7343 if (enable == in->enable_ns)
7344 goto exit;
7345
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007346 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007347 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007348 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007349 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7350 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007351 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7352 select_devices(in->dev, in->usecase);
7353 } else
7354 select_devices(in->dev, in->usecase);
7355 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007356 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007357exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007358 pthread_mutex_unlock(&in->dev->lock);
7359 pthread_mutex_unlock(&in->lock);
7360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007361 return 0;
7362}
7363
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007364static int in_add_audio_effect(const struct audio_stream *stream,
7365 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007366{
Eric Laurent994a6932013-07-17 11:51:42 -07007367 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007368 return add_remove_audio_effect(stream, effect, true);
7369}
7370
7371static int in_remove_audio_effect(const struct audio_stream *stream,
7372 effect_handle_t effect)
7373{
Eric Laurent994a6932013-07-17 11:51:42 -07007374 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007375 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007376}
7377
Derek Chenf939fb72018-11-13 13:34:41 -08007378streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7379 audio_io_handle_t input)
7380{
7381 struct listnode *node;
7382
7383 list_for_each(node, &dev->active_inputs_list) {
7384 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7385 streams_input_ctxt_t,
7386 list);
7387 if (in_ctxt->input->capture_handle == input) {
7388 return in_ctxt;
7389 }
7390 }
7391 return NULL;
7392}
7393
7394streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7395 audio_io_handle_t output)
7396{
7397 struct listnode *node;
7398
7399 list_for_each(node, &dev->active_outputs_list) {
7400 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7401 streams_output_ctxt_t,
7402 list);
7403 if (out_ctxt->output->handle == output) {
7404 return out_ctxt;
7405 }
7406 }
7407 return NULL;
7408}
7409
Haynes Mathew George16081042017-05-31 17:16:49 -07007410static int in_stop(const struct audio_stream_in* stream)
7411{
7412 struct stream_in *in = (struct stream_in *)stream;
7413 struct audio_device *adev = in->dev;
7414
7415 int ret = -ENOSYS;
7416 ALOGV("%s", __func__);
7417 pthread_mutex_lock(&adev->lock);
7418 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7419 in->capture_started && in->pcm != NULL) {
7420 pcm_stop(in->pcm);
7421 ret = stop_input_stream(in);
7422 in->capture_started = false;
7423 }
7424 pthread_mutex_unlock(&adev->lock);
7425 return ret;
7426}
7427
7428static int in_start(const struct audio_stream_in* stream)
7429{
7430 struct stream_in *in = (struct stream_in *)stream;
7431 struct audio_device *adev = in->dev;
7432 int ret = -ENOSYS;
7433
7434 ALOGV("%s in %p", __func__, in);
7435 pthread_mutex_lock(&adev->lock);
7436 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7437 !in->capture_started && in->pcm != NULL) {
7438 if (!in->capture_started) {
7439 ret = start_input_stream(in);
7440 if (ret == 0) {
7441 in->capture_started = true;
7442 }
7443 }
7444 }
7445 pthread_mutex_unlock(&adev->lock);
7446 return ret;
7447}
7448
Phil Burke0a86d12019-02-16 22:28:11 -08007449// Read offset for the positional timestamp from a persistent vendor property.
7450// This is to workaround apparent inaccuracies in the timing information that
7451// is used by the AAudio timing model. The inaccuracies can cause glitches.
7452static int64_t in_get_mmap_time_offset() {
7453 const int32_t kDefaultOffsetMicros = 0;
7454 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007455 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007456 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7457 return mmap_time_offset_micros * (int64_t)1000;
7458}
7459
Haynes Mathew George16081042017-05-31 17:16:49 -07007460static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7461 int32_t min_size_frames,
7462 struct audio_mmap_buffer_info *info)
7463{
7464 struct stream_in *in = (struct stream_in *)stream;
7465 struct audio_device *adev = in->dev;
7466 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007467 unsigned int offset1 = 0;
7468 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007469 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007470 uint32_t mmap_size = 0;
7471 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007472
7473 pthread_mutex_lock(&adev->lock);
7474 ALOGV("%s in %p", __func__, in);
7475
Sharad Sanglec6f32552018-05-04 16:15:38 +05307476 if (CARD_STATUS_OFFLINE == in->card_status||
7477 CARD_STATUS_OFFLINE == adev->card_status) {
7478 ALOGW("in->card_status or adev->card_status offline, try again");
7479 ret = -EIO;
7480 goto exit;
7481 }
7482
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307483 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007484 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7485 ret = -EINVAL;
7486 goto exit;
7487 }
7488 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7489 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7490 ALOGV("%s in %p", __func__, in);
7491 ret = -ENOSYS;
7492 goto exit;
7493 }
7494 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7495 if (in->pcm_device_id < 0) {
7496 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7497 __func__, in->pcm_device_id, in->usecase);
7498 ret = -EINVAL;
7499 goto exit;
7500 }
7501
7502 adjust_mmap_period_count(&in->config, min_size_frames);
7503
7504 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7505 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7506 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7507 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307508 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307509 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7510 in->card_status = CARD_STATUS_OFFLINE;
7511 adev->card_status = CARD_STATUS_OFFLINE;
7512 ret = -EIO;
7513 goto exit;
7514 }
7515
Haynes Mathew George16081042017-05-31 17:16:49 -07007516 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7517 step = "open";
7518 ret = -ENODEV;
7519 goto exit;
7520 }
7521
7522 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7523 if (ret < 0) {
7524 step = "begin";
7525 goto exit;
7526 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007527
juyuchen626833d2019-06-04 16:48:02 +08007528 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007529 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7530 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7531 info->burst_size_frames = in->config.period_size;
7532 ret = platform_get_mmap_data_fd(adev->platform,
7533 in->pcm_device_id, 1 /*capture*/,
7534 &info->shared_memory_fd,
7535 &mmap_size);
7536 if (ret < 0) {
7537 // Fall back to non exclusive mode
7538 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7539 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007540 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7541 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7542
Arun Mirpuri5d170872019-03-26 13:21:31 -07007543 if (mmap_size < buffer_size) {
7544 step = "mmap";
7545 goto exit;
7546 }
juyuchen626833d2019-06-04 16:48:02 +08007547 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007548 }
7549
7550 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007551
7552 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7553 if (ret < 0) {
7554 step = "commit";
7555 goto exit;
7556 }
7557
Phil Burke0a86d12019-02-16 22:28:11 -08007558 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7559
Haynes Mathew George16081042017-05-31 17:16:49 -07007560 in->standby = false;
7561 ret = 0;
7562
7563 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7564 __func__, info->shared_memory_address, info->buffer_size_frames);
7565
7566exit:
7567 if (ret != 0) {
7568 if (in->pcm == NULL) {
7569 ALOGE("%s: %s - %d", __func__, step, ret);
7570 } else {
7571 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7572 pcm_close(in->pcm);
7573 in->pcm = NULL;
7574 }
7575 }
7576 pthread_mutex_unlock(&adev->lock);
7577 return ret;
7578}
7579
7580static int in_get_mmap_position(const struct audio_stream_in *stream,
7581 struct audio_mmap_position *position)
7582{
7583 struct stream_in *in = (struct stream_in *)stream;
7584 ALOGVV("%s", __func__);
7585 if (position == NULL) {
7586 return -EINVAL;
7587 }
7588 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7589 return -ENOSYS;
7590 }
7591 if (in->pcm == NULL) {
7592 return -ENOSYS;
7593 }
7594 struct timespec ts = { 0, 0 };
7595 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7596 if (ret < 0) {
7597 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7598 return ret;
7599 }
Phil Burke0a86d12019-02-16 22:28:11 -08007600 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7601 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007602 return 0;
7603}
7604
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307605static int in_get_active_microphones(const struct audio_stream_in *stream,
7606 struct audio_microphone_characteristic_t *mic_array,
7607 size_t *mic_count) {
7608 struct stream_in *in = (struct stream_in *)stream;
7609 struct audio_device *adev = in->dev;
7610 ALOGVV("%s", __func__);
7611
7612 lock_input_stream(in);
7613 pthread_mutex_lock(&adev->lock);
7614 int ret = platform_get_active_microphones(adev->platform,
7615 audio_channel_count_from_in_mask(in->channel_mask),
7616 in->usecase, mic_array, mic_count);
7617 pthread_mutex_unlock(&adev->lock);
7618 pthread_mutex_unlock(&in->lock);
7619
7620 return ret;
7621}
7622
7623static int adev_get_microphones(const struct audio_hw_device *dev,
7624 struct audio_microphone_characteristic_t *mic_array,
7625 size_t *mic_count) {
7626 struct audio_device *adev = (struct audio_device *)dev;
7627 ALOGVV("%s", __func__);
7628
7629 pthread_mutex_lock(&adev->lock);
7630 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7631 pthread_mutex_unlock(&adev->lock);
7632
7633 return ret;
7634}
juyuchendb308c22019-01-21 11:57:17 -07007635
7636static void in_update_sink_metadata(struct audio_stream_in *stream,
7637 const struct sink_metadata *sink_metadata) {
7638
7639 if (stream == NULL
7640 || sink_metadata == NULL
7641 || sink_metadata->tracks == NULL) {
7642 return;
7643 }
7644
7645 int error = 0;
7646 struct stream_in *in = (struct stream_in *)stream;
7647 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007648 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007649 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007650
7651 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007652
7653 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007654 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007655
7656 lock_input_stream(in);
7657 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007658 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007659
Zhou Song62ea0282020-03-22 19:53:01 +08007660 is_ha_usecase = adev->ha_proxy_enable ?
7661 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7662 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7663 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007664 && adev->voice_tx_output != NULL) {
7665 /* Use the rx device from afe-proxy record to route voice call because
7666 there is no routing if tx device is on primary hal and rx device
7667 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007668 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007669
7670 if (!voice_is_call_state_active(adev)) {
7671 if (adev->mode == AUDIO_MODE_IN_CALL) {
7672 adev->current_call_output = adev->voice_tx_output;
7673 error = voice_start_call(adev);
7674 if (error != 0)
7675 ALOGE("%s: start voice call failed %d", __func__, error);
7676 }
7677 } else {
7678 adev->current_call_output = adev->voice_tx_output;
7679 voice_update_devices_for_all_voice_usecases(adev);
7680 }
7681 }
7682
7683 pthread_mutex_unlock(&adev->lock);
7684 pthread_mutex_unlock(&in->lock);
7685}
7686
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307687int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007688 audio_io_handle_t handle,
7689 audio_devices_t devices,
7690 audio_output_flags_t flags,
7691 struct audio_config *config,
7692 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007693 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007694{
7695 struct audio_device *adev = (struct audio_device *)dev;
7696 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307697 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007698 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007699 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307700 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007701 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7702 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7703 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7704 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007705 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007706 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7707 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007708 bool force_haptic_path =
7709 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007710 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007711#ifdef AUDIO_GKI_ENABLED
7712 __s32 *generic_dec;
7713#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007714
kunleizdff872d2018-08-20 14:40:33 +08007715 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007716 is_usb_dev = false;
7717 devices = AUDIO_DEVICE_OUT_SPEAKER;
7718 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7719 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007720 if (config->format == AUDIO_FORMAT_DEFAULT)
7721 config->format = AUDIO_FORMAT_PCM_16_BIT;
7722 if (config->sample_rate == 0)
7723 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7724 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7725 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007726 }
7727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007728 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307729
Rahul Sharma99770982019-03-06 17:05:26 +05307730 pthread_mutex_lock(&adev->lock);
7731 if (out_get_stream(adev, handle) != NULL) {
7732 ALOGW("%s, output stream already opened", __func__);
7733 ret = -EEXIST;
7734 }
7735 pthread_mutex_unlock(&adev->lock);
7736 if (ret)
7737 return ret;
7738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007739 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7740
Mingming Yin3a941d42016-02-17 18:08:05 -08007741 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007742 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7743 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307744
7745
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007746 if (!out) {
7747 return -ENOMEM;
7748 }
7749
Haynes Mathew George204045b2015-02-25 20:32:03 -08007750 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007751 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307752 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007753 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007754 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007756 if (devices == AUDIO_DEVICE_NONE)
7757 devices = AUDIO_DEVICE_OUT_SPEAKER;
7758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007759 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007760 list_init(&out->device_list);
7761 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007762 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007763 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007764 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307765 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307766 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7767 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7768 else
7769 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007770 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007771 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007772 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307773 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307774 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307775 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007776 out->hal_output_suspend_supported = 0;
7777 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307778 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307779 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307780 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007781 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007782
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307783 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307784 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007785 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7786
Aalique Grahame22e49102018-12-18 14:23:57 -08007787 if (direct_dev &&
7788 (audio_is_linear_pcm(out->format) ||
7789 config->format == AUDIO_FORMAT_DEFAULT) &&
7790 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7791 audio_format_t req_format = config->format;
7792 audio_channel_mask_t req_channel_mask = config->channel_mask;
7793 uint32_t req_sample_rate = config->sample_rate;
7794
7795 pthread_mutex_lock(&adev->lock);
7796 if (is_hdmi) {
7797 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7798 ret = read_hdmi_sink_caps(out);
7799 if (config->sample_rate == 0)
7800 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7801 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7802 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7803 if (config->format == AUDIO_FORMAT_DEFAULT)
7804 config->format = AUDIO_FORMAT_PCM_16_BIT;
7805 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007806 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7807 &config->format,
7808 &out->supported_formats[0],
7809 MAX_SUPPORTED_FORMATS,
7810 &config->channel_mask,
7811 &out->supported_channel_masks[0],
7812 MAX_SUPPORTED_CHANNEL_MASKS,
7813 &config->sample_rate,
7814 &out->supported_sample_rates[0],
7815 MAX_SUPPORTED_SAMPLE_RATES);
7816 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007817 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007818
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007819 pthread_mutex_unlock(&adev->lock);
7820 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007821 if (ret == -ENOSYS) {
7822 /* ignore and go with default */
7823 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007824 }
7825 // For MMAP NO IRQ, allow conversions in ADSP
7826 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7827 goto error_open;
7828 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007829 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007830 goto error_open;
7831 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007832
7833 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7834 config->sample_rate = req_sample_rate;
7835 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7836 config->channel_mask = req_channel_mask;
7837 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7838 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007839 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007840
7841 out->sample_rate = config->sample_rate;
7842 out->channel_mask = config->channel_mask;
7843 out->format = config->format;
7844 if (is_hdmi) {
7845 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7846 out->config = pcm_config_hdmi_multi;
7847 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7848 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7849 out->config = pcm_config_mmap_playback;
7850 out->stream.start = out_start;
7851 out->stream.stop = out_stop;
7852 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7853 out->stream.get_mmap_position = out_get_mmap_position;
7854 } else {
7855 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7856 out->config = pcm_config_hifi;
7857 }
7858
7859 out->config.rate = out->sample_rate;
7860 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7861 if (is_hdmi) {
7862 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7863 audio_bytes_per_sample(out->format));
7864 }
7865 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007866 }
7867
Derek Chenf6318be2017-06-12 17:16:24 -04007868 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007869 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007870 /* extract car audio stream index */
7871 out->car_audio_stream =
7872 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7873 if (out->car_audio_stream < 0) {
7874 ALOGE("%s: invalid car audio stream %x",
7875 __func__, out->car_audio_stream);
7876 ret = -EINVAL;
7877 goto error_open;
7878 }
Derek Chen5f67a942020-02-24 23:08:13 -08007879 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007880 }
7881
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007882 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007883 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007884 if (!voice_extn_is_compress_voip_supported()) {
7885 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7886 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007887 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307888 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007889 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7890 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007891 out->volume_l = INVALID_OUT_VOLUME;
7892 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007893
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007894 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007895 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007896 uint32_t channel_count =
7897 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307898 out->config.channels = channel_count;
7899
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007900 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7901 out->sample_rate, out->format,
7902 channel_count, false);
7903 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7904 if (frame_size != 0)
7905 out->config.period_size = buffer_size / frame_size;
7906 else
7907 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007908 }
7909 } else {
7910 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7911 voice_extn_compress_voip_is_active(out->dev)) &&
7912 (voice_extn_compress_voip_is_config_supported(config))) {
7913 ret = voice_extn_compress_voip_open_output_stream(out);
7914 if (ret != 0) {
7915 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7916 __func__, ret);
7917 goto error_open;
7918 }
Sujin Panicker19027262019-09-16 18:28:06 +05307919 } else {
7920 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7921 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007922 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007923 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007924 } else if (audio_is_linear_pcm(out->format) &&
7925 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7926 out->channel_mask = config->channel_mask;
7927 out->sample_rate = config->sample_rate;
7928 out->format = config->format;
7929 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7930 // does this change?
7931 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7932 out->config.rate = config->sample_rate;
7933 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7934 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7935 audio_bytes_per_sample(config->format));
7936 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007937 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307938 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307939 pthread_mutex_lock(&adev->lock);
7940 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7941 pthread_mutex_unlock(&adev->lock);
7942
7943 // reject offload during card offline to allow
7944 // fallback to s/w paths
7945 if (offline) {
7946 ret = -ENODEV;
7947 goto error_open;
7948 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007949
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007950 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7951 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7952 ALOGE("%s: Unsupported Offload information", __func__);
7953 ret = -EINVAL;
7954 goto error_open;
7955 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007956
Atul Khare3fa6e542017-08-09 00:56:17 +05307957 if (config->offload_info.format == 0)
7958 config->offload_info.format = config->format;
7959 if (config->offload_info.sample_rate == 0)
7960 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007961
Mingming Yin90310102013-11-13 16:57:00 -08007962 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307963 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007964 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007965 ret = -EINVAL;
7966 goto error_open;
7967 }
7968
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007969 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7970 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7971 (audio_extn_passthru_is_passthrough_stream(out)) &&
7972 !((config->sample_rate == 48000) ||
7973 (config->sample_rate == 96000) ||
7974 (config->sample_rate == 192000))) {
7975 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7976 __func__, config->sample_rate, config->offload_info.format);
7977 ret = -EINVAL;
7978 goto error_open;
7979 }
7980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007981 out->compr_config.codec = (struct snd_codec *)
7982 calloc(1, sizeof(struct snd_codec));
7983
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007984 if (!out->compr_config.codec) {
7985 ret = -ENOMEM;
7986 goto error_open;
7987 }
7988
Dhananjay Kumarac341582017-02-23 23:42:25 +05307989 out->stream.pause = out_pause;
7990 out->stream.resume = out_resume;
7991 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307992 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307993 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007994 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307995 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007996 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307997 } else {
7998 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7999 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008000 }
vivek mehta446c3962015-09-14 10:57:35 -07008001
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308002 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8003 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008004#ifdef AUDIO_GKI_ENABLED
8005 /* out->compr_config.codec->reserved[1] is for flags */
8006 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8007#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308008 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008009#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308010 }
8011
vivek mehta446c3962015-09-14 10:57:35 -07008012 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008013 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008014 config->format == 0 && config->sample_rate == 0 &&
8015 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008016 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008017 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8018 } else {
8019 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8020 ret = -EEXIST;
8021 goto error_open;
8022 }
vivek mehta446c3962015-09-14 10:57:35 -07008023 }
8024
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008025 if (config->offload_info.channel_mask)
8026 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008027 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008028 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008029 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008030 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308031 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008032 ret = -EINVAL;
8033 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008034 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008035
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008036 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008037 out->sample_rate = config->offload_info.sample_rate;
8038
Mingming Yin3ee55c62014-08-04 14:23:35 -07008039 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008040
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308041 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308042 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308043 audio_extn_dolby_send_ddp_endp_params(adev);
8044 audio_extn_dolby_set_dmid(adev);
8045 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008046
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008047 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008048 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008049 out->compr_config.codec->bit_rate =
8050 config->offload_info.bit_rate;
8051 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308052 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008053 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308054 /* Update bit width only for non passthrough usecases.
8055 * For passthrough usecases, the output will always be opened @16 bit
8056 */
8057 if (!audio_extn_passthru_is_passthrough_stream(out))
8058 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308059
8060 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008061#ifdef AUDIO_GKI_ENABLED
8062 /* out->compr_config.codec->reserved[1] is for flags */
8063 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8064 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8065#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308066 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8067 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008068#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308069
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008070 /*TODO: Do we need to change it for passthrough */
8071 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008072
Manish Dewangana6fc5442015-08-24 20:30:31 +05308073 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8074 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308075 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308076 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308077 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8078 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308079
8080 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8081 AUDIO_FORMAT_PCM) {
8082
8083 /*Based on platform support, configure appropriate alsa format for corresponding
8084 *hal input format.
8085 */
8086 out->compr_config.codec->format = hal_format_to_alsa(
8087 config->offload_info.format);
8088
Ashish Jain83a6cc22016-06-28 14:34:17 +05308089 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308090 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308091 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308092
Dhananjay Kumarac341582017-02-23 23:42:25 +05308093 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308094 *hal input format and alsa format might differ based on platform support.
8095 */
8096 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308097 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308098
8099 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8100
Deeraj Soman93155a62019-09-30 19:00:37 +05308101 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8102 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8103 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8104 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8105 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308106
Ashish Jainf1eaa582016-05-23 20:54:24 +05308107 /* Check if alsa session is configured with the same format as HAL input format,
8108 * if not then derive correct fragment size needed to accomodate the
8109 * conversion of HAL input format to alsa format.
8110 */
8111 audio_extn_utils_update_direct_pcm_fragment_size(out);
8112
8113 /*if hal input and output fragment size is different this indicates HAL input format is
8114 *not same as the alsa format
8115 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308116 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308117 /*Allocate a buffer to convert input data to the alsa configured format.
8118 *size of convert buffer is equal to the size required to hold one fragment size
8119 *worth of pcm data, this is because flinger does not write more than fragment_size
8120 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308121 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8122 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308123 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8124 ret = -ENOMEM;
8125 goto error_open;
8126 }
8127 }
8128 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8129 out->compr_config.fragment_size =
8130 audio_extn_passthru_get_buffer_size(&config->offload_info);
8131 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8132 } else {
8133 out->compr_config.fragment_size =
8134 platform_get_compress_offload_buffer_size(&config->offload_info);
8135 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8136 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008137
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308138 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8139 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8140 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008141 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8142#ifdef AUDIO_GKI_ENABLED
8143 generic_dec =
8144 &(out->compr_config.codec->options.generic.reserved[1]);
8145 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8146 AUDIO_OUTPUT_BIT_WIDTH;
8147#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308148 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008149#endif
8150 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008151
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308152 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8153 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8154 }
8155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008156 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8157 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008158
Manish Dewangan69426c82017-01-30 17:35:36 +05308159 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8160 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8161 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8162 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8163 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8164 } else {
8165 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8166 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008167
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308168 memset(&out->channel_map_param, 0,
8169 sizeof(struct audio_out_channel_map_param));
8170
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008171 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308172 out->send_next_track_params = false;
8173 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008174 out->offload_state = OFFLOAD_STATE_IDLE;
8175 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008176 out->writeAt.tv_sec = 0;
8177 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008178
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008179 audio_extn_dts_create_state_notifier_node(out->usecase);
8180
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008181 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8182 __func__, config->offload_info.version,
8183 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308184
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308185 /* Check if DSD audio format is supported in codec
8186 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308187 */
8188
8189 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308190 (!platform_check_codec_dsd_support(adev->platform) ||
8191 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308192 ret = -EINVAL;
8193 goto error_open;
8194 }
8195
Ashish Jain5106d362016-05-11 19:23:33 +05308196 /* Disable gapless if any of the following is true
8197 * passthrough playback
8198 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308199 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308200 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308201 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308202 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008203 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308204 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308205 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308206 check_and_set_gapless_mode(adev, false);
8207 } else
8208 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008209
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308210 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008211 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8212 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308213 if (config->format == AUDIO_FORMAT_DSD) {
8214 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008215#ifdef AUDIO_GKI_ENABLED
8216 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8217 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8218#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308219 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008220#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308221 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008222
8223 create_offload_callback_thread(out);
8224
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008225 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008226 switch (config->sample_rate) {
8227 case 0:
8228 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8229 break;
8230 case 8000:
8231 case 16000:
8232 case 48000:
8233 out->sample_rate = config->sample_rate;
8234 break;
8235 default:
8236 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8237 config->sample_rate);
8238 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8239 ret = -EINVAL;
8240 goto error_open;
8241 }
8242 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8243 switch (config->channel_mask) {
8244 case AUDIO_CHANNEL_NONE:
8245 case AUDIO_CHANNEL_OUT_STEREO:
8246 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8247 break;
8248 default:
8249 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8250 config->channel_mask);
8251 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8252 ret = -EINVAL;
8253 goto error_open;
8254 }
8255 switch (config->format) {
8256 case AUDIO_FORMAT_DEFAULT:
8257 case AUDIO_FORMAT_PCM_16_BIT:
8258 out->format = AUDIO_FORMAT_PCM_16_BIT;
8259 break;
8260 default:
8261 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8262 config->format);
8263 config->format = AUDIO_FORMAT_PCM_16_BIT;
8264 ret = -EINVAL;
8265 goto error_open;
8266 }
8267
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308268 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008269 if (ret != 0) {
8270 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008271 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008272 goto error_open;
8273 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008274 } else if (is_single_device_type_equal(&out->device_list,
8275 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008276 switch (config->sample_rate) {
8277 case 0:
8278 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8279 break;
8280 case 8000:
8281 case 16000:
8282 case 48000:
8283 out->sample_rate = config->sample_rate;
8284 break;
8285 default:
8286 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8287 config->sample_rate);
8288 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8289 ret = -EINVAL;
8290 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008291 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008292 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8293 switch (config->channel_mask) {
8294 case AUDIO_CHANNEL_NONE:
8295 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8296 break;
8297 case AUDIO_CHANNEL_OUT_STEREO:
8298 out->channel_mask = config->channel_mask;
8299 break;
8300 default:
8301 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8302 config->channel_mask);
8303 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8304 ret = -EINVAL;
8305 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008306 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008307 switch (config->format) {
8308 case AUDIO_FORMAT_DEFAULT:
8309 out->format = AUDIO_FORMAT_PCM_16_BIT;
8310 break;
8311 case AUDIO_FORMAT_PCM_16_BIT:
8312 out->format = config->format;
8313 break;
8314 default:
8315 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8316 config->format);
8317 config->format = AUDIO_FORMAT_PCM_16_BIT;
8318 ret = -EINVAL;
8319 break;
8320 }
8321 if (ret != 0)
8322 goto error_open;
8323
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008324 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8325 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008326 out->config.rate = out->sample_rate;
8327 out->config.channels =
8328 audio_channel_count_from_out_mask(out->channel_mask);
8329 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008330 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008331 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308332 unsigned int channels = 0;
8333 /*Update config params to default if not set by the caller*/
8334 if (config->sample_rate == 0)
8335 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8336 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8337 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8338 if (config->format == AUDIO_FORMAT_DEFAULT)
8339 config->format = AUDIO_FORMAT_PCM_16_BIT;
8340
8341 channels = audio_channel_count_from_out_mask(out->channel_mask);
8342
Varun Balaraje49253e2017-07-06 19:48:56 +05308343 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8344 out->usecase = get_interactive_usecase(adev);
8345 out->config = pcm_config_low_latency;
8346 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308347 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008348 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8349 out->flags);
8350 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008351 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8352 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8353 out->config = pcm_config_mmap_playback;
8354 out->stream.start = out_start;
8355 out->stream.stop = out_stop;
8356 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8357 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308358 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8359 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008360 out->hal_output_suspend_supported =
8361 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8362 out->dynamic_pm_qos_config_supported =
8363 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8364 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008365 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8366 } else {
8367 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8368 //the mixer path will be a string similar to "low-latency-playback resume"
8369 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8370 strlcat(out->pm_qos_mixer_path,
8371 " resume", MAX_MIXER_PATH_LEN);
8372 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8373 out->pm_qos_mixer_path);
8374 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308375 out->config = pcm_config_low_latency;
8376 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8377 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8378 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308379 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8380 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8381 if (out->config.period_size <= 0) {
8382 ALOGE("Invalid configuration period size is not valid");
8383 ret = -EINVAL;
8384 goto error_open;
8385 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008386 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8387 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8388 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008389 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8390 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8391 out->config = pcm_config_haptics_audio;
8392 if (force_haptic_path)
8393 adev->haptics_config = pcm_config_haptics_audio;
8394 else
8395 adev->haptics_config = pcm_config_haptics;
8396
Meng Wangd08ce322020-04-02 08:59:20 +08008397 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008398 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8399
8400 if (force_haptic_path) {
8401 out->config.channels = 1;
8402 adev->haptics_config.channels = 1;
8403 } else
8404 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 -08008405 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008406 ret = audio_extn_auto_hal_open_output_stream(out);
8407 if (ret) {
8408 ALOGE("%s: Failed to open output stream for bus device", __func__);
8409 ret = -EINVAL;
8410 goto error_open;
8411 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308412 } else {
8413 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008414 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8415 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308416 }
8417 out->hal_ip_format = format = out->format;
8418 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8419 out->hal_op_format = pcm_format_to_hal(out->config.format);
8420 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8421 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008422 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308423 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308424 if (out->hal_ip_format != out->hal_op_format) {
8425 uint32_t buffer_size = out->config.period_size *
8426 format_to_bitwidth_table[out->hal_op_format] *
8427 out->config.channels;
8428 out->convert_buffer = calloc(1, buffer_size);
8429 if (out->convert_buffer == NULL){
8430 ALOGE("Allocation failed for convert buffer for size %d",
8431 out->compr_config.fragment_size);
8432 ret = -ENOMEM;
8433 goto error_open;
8434 }
8435 ALOGD("Convert buffer allocated of size %d", buffer_size);
8436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008437 }
8438
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008439 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8440 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308441
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008442 /* TODO remove this hardcoding and check why width is zero*/
8443 if (out->bit_width == 0)
8444 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308445 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008446 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008447 &out->device_list, out->flags,
8448 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308449 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308450 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008451 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008452 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8453 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008454 if(adev->primary_output == NULL)
8455 adev->primary_output = out;
8456 else {
8457 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008458 ret = -EEXIST;
8459 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008460 }
8461 }
8462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008463 /* Check if this usecase is already existing */
8464 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008465 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8466 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008468 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008469 ret = -EEXIST;
8470 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008471 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008473 pthread_mutex_unlock(&adev->lock);
8474
8475 out->stream.common.get_sample_rate = out_get_sample_rate;
8476 out->stream.common.set_sample_rate = out_set_sample_rate;
8477 out->stream.common.get_buffer_size = out_get_buffer_size;
8478 out->stream.common.get_channels = out_get_channels;
8479 out->stream.common.get_format = out_get_format;
8480 out->stream.common.set_format = out_set_format;
8481 out->stream.common.standby = out_standby;
8482 out->stream.common.dump = out_dump;
8483 out->stream.common.set_parameters = out_set_parameters;
8484 out->stream.common.get_parameters = out_get_parameters;
8485 out->stream.common.add_audio_effect = out_add_audio_effect;
8486 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8487 out->stream.get_latency = out_get_latency;
8488 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008489#ifdef NO_AUDIO_OUT
8490 out->stream.write = out_write_for_no_output;
8491#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008492 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008493#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008494 out->stream.get_render_position = out_get_render_position;
8495 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008496 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008497
Haynes Mathew George16081042017-05-31 17:16:49 -07008498 if (out->realtime)
8499 out->af_period_multiplier = af_period_multiplier;
8500 else
8501 out->af_period_multiplier = 1;
8502
Andy Hunga1f48fa2019-07-01 18:14:53 -07008503 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008506 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008507 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008508
8509 config->format = out->stream.common.get_format(&out->stream.common);
8510 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8511 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308512 register_format(out->format, out->supported_formats);
8513 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8514 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008515
Aalique Grahame22e49102018-12-18 14:23:57 -08008516 out->error_log = error_log_create(
8517 ERROR_LOG_ENTRIES,
8518 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8519
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308520 /*
8521 By locking output stream before registering, we allow the callback
8522 to update stream's state only after stream's initial state is set to
8523 adev state.
8524 */
8525 lock_output_stream(out);
8526 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8527 pthread_mutex_lock(&adev->lock);
8528 out->card_status = adev->card_status;
8529 pthread_mutex_unlock(&adev->lock);
8530 pthread_mutex_unlock(&out->lock);
8531
Aalique Grahame22e49102018-12-18 14:23:57 -08008532 stream_app_type_cfg_init(&out->app_type_cfg);
8533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308535 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008536 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008537
8538 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8539 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8540 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008541 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308542 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008543 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008544 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308545 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8546 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008547 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8548 out->usecase, PCM_PLAYBACK);
8549 hdlr_stream_cfg.flags = out->flags;
8550 hdlr_stream_cfg.type = PCM_PLAYBACK;
8551 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8552 &hdlr_stream_cfg);
8553 if (ret) {
8554 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8555 out->adsp_hdlr_stream_handle = NULL;
8556 }
8557 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308558 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8559 is_direct_passthough, false);
8560 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8561 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008562 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008563 if (ret < 0) {
8564 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8565 out->ip_hdlr_handle = NULL;
8566 }
8567 }
Derek Chenf939fb72018-11-13 13:34:41 -08008568
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008569 ret = io_streams_map_insert(adev, &out->stream.common,
8570 out->handle, AUDIO_PATCH_HANDLE_NONE);
8571 if (ret != 0)
8572 goto error_open;
8573
Derek Chenf939fb72018-11-13 13:34:41 -08008574 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8575 calloc(1, sizeof(streams_output_ctxt_t));
8576 if (out_ctxt == NULL) {
8577 ALOGE("%s fail to allocate output ctxt", __func__);
8578 ret = -ENOMEM;
8579 goto error_open;
8580 }
8581 out_ctxt->output = out;
8582
8583 pthread_mutex_lock(&adev->lock);
8584 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8585 pthread_mutex_unlock(&adev->lock);
8586
Eric Laurent994a6932013-07-17 11:51:42 -07008587 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008588 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008589
8590error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308591 if (out->convert_buffer)
8592 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008593 free(out);
8594 *stream_out = NULL;
8595 ALOGD("%s: exit: ret %d", __func__, ret);
8596 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008597}
8598
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308599void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008600 struct audio_stream_out *stream)
8601{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008602 struct stream_out *out = (struct stream_out *)stream;
8603 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008604 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008605
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008606 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308607
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008608 io_streams_map_remove(adev, out->handle);
8609
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308610 // must deregister from sndmonitor first to prevent races
8611 // between the callback and close_stream
8612 audio_extn_snd_mon_unregister_listener(out);
8613
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008614 /* close adsp hdrl session before standby */
8615 if (out->adsp_hdlr_stream_handle) {
8616 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8617 if (ret)
8618 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8619 out->adsp_hdlr_stream_handle = NULL;
8620 }
8621
Manish Dewangan21a850a2017-08-14 12:03:55 +05308622 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008623 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8624 out->ip_hdlr_handle = NULL;
8625 }
8626
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008627 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308628 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008629 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308630 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308631 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008632 if(ret != 0)
8633 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8634 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008635 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008636 out_standby(&stream->common);
8637
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008638 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008639 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008640 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008641 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008642 if (out->compr_config.codec != NULL)
8643 free(out->compr_config.codec);
8644 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008645
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308646 out->a2dp_compress_mute = false;
8647
Varun Balaraje49253e2017-07-06 19:48:56 +05308648 if (is_interactive_usecase(out->usecase))
8649 free_interactive_usecase(adev, out->usecase);
8650
Ashish Jain83a6cc22016-06-28 14:34:17 +05308651 if (out->convert_buffer != NULL) {
8652 free(out->convert_buffer);
8653 out->convert_buffer = NULL;
8654 }
8655
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008656 if (adev->voice_tx_output == out)
8657 adev->voice_tx_output = NULL;
8658
Aalique Grahame22e49102018-12-18 14:23:57 -08008659 error_log_destroy(out->error_log);
8660 out->error_log = NULL;
8661
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308662 if (adev->primary_output == out)
8663 adev->primary_output = NULL;
8664
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008665 pthread_cond_destroy(&out->cond);
8666 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008667
8668 pthread_mutex_lock(&adev->lock);
8669 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8670 if (out_ctxt != NULL) {
8671 list_remove(&out_ctxt->list);
8672 free(out_ctxt);
8673 } else {
8674 ALOGW("%s, output stream already closed", __func__);
8675 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008676 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008677 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008678 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008679}
8680
8681static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8682{
8683 struct audio_device *adev = (struct audio_device *)dev;
8684 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008685 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008686 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008687 int ret;
8688 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008689 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008690 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008691 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008692
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008693 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008694 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008695
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308696 if (!parms)
8697 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308698
Derek Chen6f293672019-04-01 01:40:24 -07008699 /* notify adev and input/output streams on the snd card status */
8700 adev_snd_mon_cb((void *)adev, parms);
8701
8702 list_for_each(node, &adev->active_outputs_list) {
8703 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8704 streams_output_ctxt_t,
8705 list);
8706 out_snd_mon_cb((void *)out_ctxt->output, parms);
8707 }
8708
8709 list_for_each(node, &adev->active_inputs_list) {
8710 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8711 streams_input_ctxt_t,
8712 list);
8713 in_snd_mon_cb((void *)in_ctxt->input, parms);
8714 }
8715
Zhou Songd6d71752019-05-21 18:08:51 +08008716 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308717 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8718 if (ret >= 0) {
8719 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008720 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308721 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008722 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308723 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008724 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008725 }
8726 }
8727
8728 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8729 if (ret>=0) {
8730 if (!strncmp(value, "false", 5) &&
8731 audio_extn_a2dp_source_is_suspended()) {
8732 struct audio_usecase *usecase;
8733 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008734 list_for_each(node, &adev->usecase_list) {
8735 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008736 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008737 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008738 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008739 reassign_device_list(&usecase->stream.in->device_list,
8740 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008741 select_devices(adev, usecase->id);
8742 }
Zhou Songd6d71752019-05-21 18:08:51 +08008743 }
8744 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308745 }
8746
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008747 status = voice_set_parameters(adev, parms);
8748 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008749 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008750
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008751 status = platform_set_parameters(adev->platform, parms);
8752 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008753 goto done;
8754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008755 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8756 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008757 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008758 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8759 adev->bluetooth_nrec = true;
8760 else
8761 adev->bluetooth_nrec = false;
8762 }
8763
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008764 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8765 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8767 adev->screen_off = false;
8768 else
8769 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008770 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008771 }
8772
Eric Laurent4b084132018-10-19 17:33:43 -07008773 ret = str_parms_get_int(parms, "rotation", &val);
8774 if (ret >= 0) {
8775 bool reverse_speakers = false;
8776 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8777 switch (val) {
8778 // FIXME: note that the code below assumes that the speakers are in the correct placement
8779 // relative to the user when the device is rotated 90deg from its default rotation. This
8780 // assumption is device-specific, not platform-specific like this code.
8781 case 270:
8782 reverse_speakers = true;
8783 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8784 break;
8785 case 0:
8786 case 180:
8787 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8788 break;
8789 case 90:
8790 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8791 break;
8792 default:
8793 ALOGE("%s: unexpected rotation of %d", __func__, val);
8794 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008795 }
Eric Laurent4b084132018-10-19 17:33:43 -07008796 if (status == 0) {
8797 // check and set swap
8798 // - check if orientation changed and speaker active
8799 // - set rotation and cache the rotation value
8800 adev->camera_orientation =
8801 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8802 if (!audio_extn_is_maxx_audio_enabled())
8803 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8804 }
8805 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008806
Mingming Yin514a8bc2014-07-29 15:22:21 -07008807 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8808 if (ret >= 0) {
8809 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8810 adev->bt_wb_speech_enabled = true;
8811 else
8812 adev->bt_wb_speech_enabled = false;
8813 }
8814
Zhou Song12c29502019-03-16 10:37:18 +08008815 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8816 if (ret >= 0) {
8817 val = atoi(value);
8818 adev->swb_speech_mode = val;
8819 }
8820
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008821 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8822 if (ret >= 0) {
8823 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308824 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008825 if (audio_is_output_device(val) &&
8826 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008827 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008828 platform_get_controller_stream_from_params(parms, &controller, &stream);
8829 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8830 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008831 if (ret < 0) {
8832 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308833 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008834 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008835 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308836 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008837 /*
8838 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8839 * Per AudioPolicyManager, USB device is higher priority than WFD.
8840 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8841 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8842 * starting voice call on USB
8843 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008844 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308845 if (ret >= 0)
8846 audio_extn_usb_add_device(device, atoi(value));
8847
Zhou Song6f862822017-11-06 17:27:57 +08008848 if (!audio_extn_usb_is_tunnel_supported()) {
8849 ALOGV("detected USB connect .. disable proxy");
8850 adev->allow_afe_proxy_usage = false;
8851 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008852 }
8853 }
8854
8855 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8856 if (ret >= 0) {
8857 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308858 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008859 /*
8860 * The HDMI / Displayport disconnect handling has been moved to
8861 * audio extension to ensure that its parameters are not
8862 * invalidated prior to updating sysfs of the disconnect event
8863 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8864 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308865 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008866 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308867 if (ret >= 0)
8868 audio_extn_usb_remove_device(device, atoi(value));
8869
Zhou Song6f862822017-11-06 17:27:57 +08008870 if (!audio_extn_usb_is_tunnel_supported()) {
8871 ALOGV("detected USB disconnect .. enable proxy");
8872 adev->allow_afe_proxy_usage = true;
8873 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008874 }
8875 }
8876
Aalique Grahame22e49102018-12-18 14:23:57 -08008877 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008878 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008879
8880 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008881 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308882 struct audio_usecase *usecase;
8883 struct listnode *node;
8884 list_for_each(node, &adev->usecase_list) {
8885 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008886 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8887 continue;
8888
8889 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308890 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008891 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308892 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008893 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308894 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308895 ALOGD("Switching to speaker and muting the stream before select_devices");
8896 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308897 //force device switch to re configure encoder
8898 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308899 ALOGD("Unmuting the stream after select_devices");
8900 usecase->stream.out->a2dp_compress_mute = false;
8901 out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308902 audio_extn_a2dp_set_handoff_mode(false);
8903 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308904 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308905 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8906 usecase->stream.out->a2dp_compress_mute) {
8907 pthread_mutex_unlock(&adev->lock);
8908 lock_output_stream(usecase->stream.out);
8909 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008910 reassign_device_list(&usecase->stream.out->device_list,
8911 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308912 check_a2dp_restore_l(adev, usecase->stream.out, true);
8913 pthread_mutex_unlock(&usecase->stream.out->lock);
8914 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308915 }
8916 }
8917 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008918
8919 //handle vr audio setparam
8920 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8921 value, sizeof(value));
8922 if (ret >= 0) {
8923 ALOGI("Setting vr mode to be %s", value);
8924 if (!strncmp(value, "true", 4)) {
8925 adev->vr_audio_mode_enabled = true;
8926 ALOGI("Setting vr mode to true");
8927 } else if (!strncmp(value, "false", 5)) {
8928 adev->vr_audio_mode_enabled = false;
8929 ALOGI("Setting vr mode to false");
8930 } else {
8931 ALOGI("wrong vr mode set");
8932 }
8933 }
8934
Eric Laurent4b084132018-10-19 17:33:43 -07008935 //FIXME: to be replaced by proper video capture properties API
8936 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8937 if (ret >= 0) {
8938 int camera_facing = CAMERA_FACING_BACK;
8939 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8940 camera_facing = CAMERA_FACING_FRONT;
8941 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8942 camera_facing = CAMERA_FACING_BACK;
8943 else {
8944 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8945 goto done;
8946 }
8947 adev->camera_orientation =
8948 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8949 struct audio_usecase *usecase;
8950 struct listnode *node;
8951 list_for_each(node, &adev->usecase_list) {
8952 usecase = node_to_item(node, struct audio_usecase, list);
8953 struct stream_in *in = usecase->stream.in;
8954 if (usecase->type == PCM_CAPTURE && in != NULL &&
8955 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8956 select_devices(adev, in->usecase);
8957 }
8958 }
8959 }
8960
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308961 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008962done:
8963 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008964 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308965error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008966 ALOGV("%s: exit with code(%d)", __func__, status);
8967 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008968}
8969
8970static char* adev_get_parameters(const struct audio_hw_device *dev,
8971 const char *keys)
8972{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308973 ALOGD("%s:%s", __func__, keys);
8974
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008975 struct audio_device *adev = (struct audio_device *)dev;
8976 struct str_parms *reply = str_parms_create();
8977 struct str_parms *query = str_parms_create_str(keys);
8978 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308979 char value[256] = {0};
8980 int ret = 0;
8981
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008982 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008983 if (reply) {
8984 str_parms_destroy(reply);
8985 }
8986 if (query) {
8987 str_parms_destroy(query);
8988 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008989 ALOGE("adev_get_parameters: failed to create query or reply");
8990 return NULL;
8991 }
8992
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008993 //handle vr audio getparam
8994
8995 ret = str_parms_get_str(query,
8996 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8997 value, sizeof(value));
8998
8999 if (ret >= 0) {
9000 bool vr_audio_enabled = false;
9001 pthread_mutex_lock(&adev->lock);
9002 vr_audio_enabled = adev->vr_audio_mode_enabled;
9003 pthread_mutex_unlock(&adev->lock);
9004
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009005 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009006
9007 if (vr_audio_enabled) {
9008 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9009 "true");
9010 goto exit;
9011 } else {
9012 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9013 "false");
9014 goto exit;
9015 }
9016 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009017
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009018 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009019 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009020 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009021 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009022 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009023 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309024 pthread_mutex_unlock(&adev->lock);
9025
Naresh Tannirud7205b62014-06-20 02:54:48 +05309026exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009027 str = str_parms_to_str(reply);
9028 str_parms_destroy(query);
9029 str_parms_destroy(reply);
9030
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009031 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009032 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009033}
9034
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009035static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036{
9037 return 0;
9038}
9039
9040static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9041{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009042 int ret;
9043 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009044
9045 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9046
Haynes Mathew George5191a852013-09-11 14:19:36 -07009047 pthread_mutex_lock(&adev->lock);
9048 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009049 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009050 pthread_mutex_unlock(&adev->lock);
9051 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009052}
9053
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009054static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9055 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009056{
9057 return -ENOSYS;
9058}
9059
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009060static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9061 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009062{
9063 return -ENOSYS;
9064}
9065
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009066static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9067 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009068{
9069 return -ENOSYS;
9070}
9071
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009072static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9073 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009074{
9075 return -ENOSYS;
9076}
9077
9078static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9079{
9080 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009081 struct listnode *node;
9082 struct audio_usecase *usecase = NULL;
9083 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009085 pthread_mutex_lock(&adev->lock);
9086 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309087 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9088 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009089 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309090 if( mode == AUDIO_MODE_CALL_SCREEN ){
9091 adev->current_call_output = adev->primary_output;
9092 voice_start_call(adev);
9093 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009094 (mode == AUDIO_MODE_NORMAL ||
9095 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009096 list_for_each(node, &adev->usecase_list) {
9097 usecase = node_to_item(node, struct audio_usecase, list);
9098 if (usecase->type == VOICE_CALL)
9099 break;
9100 }
9101 if (usecase &&
9102 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9103 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9104 true);
9105 if (ret != 0) {
9106 /* default service interval was successfully updated,
9107 reopen USB backend with new service interval */
9108 check_usecases_codec_backend(adev,
9109 usecase,
9110 usecase->out_snd_device);
9111 }
9112 }
9113
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009114 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009115 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009116 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009117 // restore device for other active usecases after stop call
9118 list_for_each(node, &adev->usecase_list) {
9119 usecase = node_to_item(node, struct audio_usecase, list);
9120 select_devices(adev, usecase->id);
9121 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123 }
9124 pthread_mutex_unlock(&adev->lock);
9125 return 0;
9126}
9127
9128static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9129{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009130 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009131 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009132
9133 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009134 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009135 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009136
Derek Chend2530072014-11-24 12:39:14 -08009137 if (adev->ext_hw_plugin)
9138 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009139
9140 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009141 pthread_mutex_unlock(&adev->lock);
9142
9143 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144}
9145
9146static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9147{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009148 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149 return 0;
9150}
9151
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009152static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009153 const struct audio_config *config)
9154{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009155 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156
Aalique Grahame22e49102018-12-18 14:23:57 -08009157 /* Don't know if USB HIFI in this context so use true to be conservative */
9158 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9159 true /*is_usb_hifi */) != 0)
9160 return 0;
9161
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009162 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9163 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009164}
9165
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009166static bool adev_input_allow_hifi_record(struct audio_device *adev,
9167 audio_devices_t devices,
9168 audio_input_flags_t flags,
9169 audio_source_t source) {
9170 const bool allowed = true;
9171
9172 if (!audio_is_usb_in_device(devices))
9173 return !allowed;
9174
9175 switch (flags) {
9176 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009177 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009178 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9179 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009180 default:
9181 return !allowed;
9182 }
9183
9184 switch (source) {
9185 case AUDIO_SOURCE_DEFAULT:
9186 case AUDIO_SOURCE_MIC:
9187 case AUDIO_SOURCE_UNPROCESSED:
9188 break;
9189 default:
9190 return !allowed;
9191 }
9192
9193 switch (adev->mode) {
9194 case 0:
9195 break;
9196 default:
9197 return !allowed;
9198 }
9199
9200 return allowed;
9201}
9202
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009203static int adev_update_voice_comm_input_stream(struct stream_in *in,
9204 struct audio_config *config)
9205{
9206 bool valid_rate = (config->sample_rate == 8000 ||
9207 config->sample_rate == 16000 ||
9208 config->sample_rate == 32000 ||
9209 config->sample_rate == 48000);
9210 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9211
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009212 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009213 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009214 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9215 in->config = default_pcm_config_voip_copp;
9216 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9217 DEFAULT_VOIP_BUF_DURATION_MS,
9218 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009219 } else {
9220 ALOGW("%s No valid input in voip, use defaults"
9221 "sample rate %u, channel mask 0x%X",
9222 __func__, config->sample_rate, in->channel_mask);
9223 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009224 in->config.rate = config->sample_rate;
9225 in->sample_rate = config->sample_rate;
9226 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009227 //XXX needed for voice_extn_compress_voip_open_input_stream
9228 in->config.rate = config->sample_rate;
9229 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309230 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009231 voice_extn_compress_voip_is_active(in->dev)) &&
9232 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9233 valid_rate && valid_ch) {
9234 voice_extn_compress_voip_open_input_stream(in);
9235 // update rate entries to match config from AF
9236 in->config.rate = config->sample_rate;
9237 in->sample_rate = config->sample_rate;
9238 } else {
9239 ALOGW("%s compress voip not active, use defaults", __func__);
9240 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009241 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009242 return 0;
9243}
9244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009245static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009246 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009247 audio_devices_t devices,
9248 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009249 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309250 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009251 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009252 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009253{
9254 struct audio_device *adev = (struct audio_device *)dev;
9255 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009256 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009257 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009258 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309259 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009260 bool is_usb_dev = audio_is_usb_in_device(devices);
9261 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9262 devices,
9263 flags,
9264 source);
Andy Hung94320602018-10-29 18:31:12 -07009265 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9266 " sample_rate %u, channel_mask %#x, format %#x",
9267 __func__, flags, is_usb_dev, may_use_hifi_record,
9268 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309269
kunleizdff872d2018-08-20 14:40:33 +08009270 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009271 is_usb_dev = false;
9272 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9273 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9274 __func__, devices);
9275 }
9276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009277 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009278
9279 if (!(is_usb_dev && may_use_hifi_record)) {
9280 if (config->sample_rate == 0)
9281 config->sample_rate = 48000;
9282 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9283 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9284 if (config->format == AUDIO_FORMAT_DEFAULT)
9285 config->format = AUDIO_FORMAT_PCM_16_BIT;
9286
9287 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9288
Aalique Grahame22e49102018-12-18 14:23:57 -08009289 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9290 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009291 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009293
Rahul Sharma99770982019-03-06 17:05:26 +05309294 pthread_mutex_lock(&adev->lock);
9295 if (in_get_stream(adev, handle) != NULL) {
9296 ALOGW("%s, input stream already opened", __func__);
9297 ret = -EEXIST;
9298 }
9299 pthread_mutex_unlock(&adev->lock);
9300 if (ret)
9301 return ret;
9302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009303 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009304
9305 if (!in) {
9306 ALOGE("failed to allocate input stream");
9307 return -ENOMEM;
9308 }
9309
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309310 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309311 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9312 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009313 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009314 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009316 in->stream.common.get_sample_rate = in_get_sample_rate;
9317 in->stream.common.set_sample_rate = in_set_sample_rate;
9318 in->stream.common.get_buffer_size = in_get_buffer_size;
9319 in->stream.common.get_channels = in_get_channels;
9320 in->stream.common.get_format = in_get_format;
9321 in->stream.common.set_format = in_set_format;
9322 in->stream.common.standby = in_standby;
9323 in->stream.common.dump = in_dump;
9324 in->stream.common.set_parameters = in_set_parameters;
9325 in->stream.common.get_parameters = in_get_parameters;
9326 in->stream.common.add_audio_effect = in_add_audio_effect;
9327 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9328 in->stream.set_gain = in_set_gain;
9329 in->stream.read = in_read;
9330 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009331 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309332 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009333 in->stream.set_microphone_direction = in_set_microphone_direction;
9334 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009335 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009336
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009337 list_init(&in->device_list);
9338 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009339 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009340 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009341 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009342 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009343 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009344 in->bit_width = 16;
9345 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009346 in->direction = MIC_DIRECTION_UNSPECIFIED;
9347 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009348 list_init(&in->aec_list);
9349 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009350 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009351
Andy Hung94320602018-10-29 18:31:12 -07009352 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009353 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9354 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9355 /* Force channel config requested to mono if incall
9356 record is being requested for only uplink/downlink */
9357 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9358 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9359 ret = -EINVAL;
9360 goto err_open;
9361 }
9362 }
9363
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009364 if (is_usb_dev && may_use_hifi_record) {
9365 /* HiFi record selects an appropriate format, channel, rate combo
9366 depending on sink capabilities*/
9367 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9368 &config->format,
9369 &in->supported_formats[0],
9370 MAX_SUPPORTED_FORMATS,
9371 &config->channel_mask,
9372 &in->supported_channel_masks[0],
9373 MAX_SUPPORTED_CHANNEL_MASKS,
9374 &config->sample_rate,
9375 &in->supported_sample_rates[0],
9376 MAX_SUPPORTED_SAMPLE_RATES);
9377 if (ret != 0) {
9378 ret = -EINVAL;
9379 goto err_open;
9380 }
9381 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009382 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309383 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309384 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9385 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9386 in->config.format = PCM_FORMAT_S32_LE;
9387 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309388 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9389 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9390 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9391 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9392 bool ret_error = false;
9393 in->bit_width = 24;
9394 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9395 from HAL is 24_packed and 8_24
9396 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9397 24_packed return error indicating supported format is 24_packed
9398 *> In case of any other source requesting 24 bit or float return error
9399 indicating format supported is 16 bit only.
9400
9401 on error flinger will retry with supported format passed
9402 */
9403 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9404 (source != AUDIO_SOURCE_CAMCORDER)) {
9405 config->format = AUDIO_FORMAT_PCM_16_BIT;
9406 if (config->sample_rate > 48000)
9407 config->sample_rate = 48000;
9408 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009409 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9410 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309411 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9412 ret_error = true;
9413 }
9414
9415 if (ret_error) {
9416 ret = -EINVAL;
9417 goto err_open;
9418 }
9419 }
9420
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009421 in->channel_mask = config->channel_mask;
9422 in->format = config->format;
9423
9424 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309425
9426 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9427 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9428 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9429 else {
9430 ret = -EINVAL;
9431 goto err_open;
9432 }
9433 }
9434
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009435 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309436 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9437 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009438 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9439 is_low_latency = true;
9440#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309441 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9442 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9443 else
9444 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009445#endif
9446 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009447 if (!in->realtime) {
9448 in->config = pcm_config_audio_capture;
9449 frame_size = audio_stream_in_frame_size(&in->stream);
9450 buffer_size = get_input_buffer_size(config->sample_rate,
9451 config->format,
9452 channel_count,
9453 is_low_latency);
9454 in->config.period_size = buffer_size / frame_size;
9455 in->config.rate = config->sample_rate;
9456 in->af_period_multiplier = 1;
9457 } else {
9458 // period size is left untouched for rt mode playback
9459 in->config = pcm_config_audio_capture_rt;
9460 in->af_period_multiplier = af_period_multiplier;
9461 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009462 }
9463
9464 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9465 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9466 in->realtime = 0;
9467 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9468 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009469 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009470 in->stream.start = in_start;
9471 in->stream.stop = in_stop;
9472 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9473 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009474 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009475 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009476 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9477 in->config = pcm_config_audio_capture;
9478 frame_size = audio_stream_in_frame_size(&in->stream);
9479 buffer_size = get_input_buffer_size(config->sample_rate,
9480 config->format,
9481 channel_count,
9482 false /*is_low_latency*/);
9483 in->config.period_size = buffer_size / frame_size;
9484 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009485 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009486 switch (config->format) {
9487 case AUDIO_FORMAT_PCM_32_BIT:
9488 in->bit_width = 32;
9489 break;
9490 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9491 case AUDIO_FORMAT_PCM_8_24_BIT:
9492 in->bit_width = 24;
9493 break;
9494 default:
9495 in->bit_width = 16;
9496 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009497 } else if (is_single_device_type_equal(&in->device_list,
9498 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9499 is_single_device_type_equal(&in->device_list,
9500 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009501 if (config->sample_rate == 0)
9502 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9503 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9504 config->sample_rate != 8000) {
9505 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9506 ret = -EINVAL;
9507 goto err_open;
9508 }
9509 if (config->format == AUDIO_FORMAT_DEFAULT)
9510 config->format = AUDIO_FORMAT_PCM_16_BIT;
9511 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9512 config->format = AUDIO_FORMAT_PCM_16_BIT;
9513 ret = -EINVAL;
9514 goto err_open;
9515 }
9516
9517 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009518 if (adev->ha_proxy_enable &&
9519 is_single_device_type_equal(&in->device_list,
9520 AUDIO_DEVICE_IN_TELEPHONY_RX))
9521 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009522 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009523 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009524 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309525 } else if (in->realtime) {
9526 in->config = pcm_config_audio_capture_rt;
9527 in->config.format = pcm_format_from_audio_format(config->format);
9528 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009529 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9530 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9531 (config->sample_rate == 8000 ||
9532 config->sample_rate == 16000 ||
9533 config->sample_rate == 32000 ||
9534 config->sample_rate == 48000) &&
9535 channel_count == 1) {
9536 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9537 in->config = pcm_config_audio_capture;
9538 frame_size = audio_stream_in_frame_size(&in->stream);
9539 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9540 config->sample_rate,
9541 config->format,
9542 channel_count, false /*is_low_latency*/);
9543 in->config.period_size = buffer_size / frame_size;
9544 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9545 in->config.rate = config->sample_rate;
9546 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009547 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309548 int ret_val;
9549 pthread_mutex_lock(&adev->lock);
9550 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9551 in, config, &channel_mask_updated);
9552 pthread_mutex_unlock(&adev->lock);
9553
9554 if (!ret_val) {
9555 if (channel_mask_updated == true) {
9556 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9557 __func__, config->channel_mask);
9558 ret = -EINVAL;
9559 goto err_open;
9560 }
9561 ALOGD("%s: created multi-channel session succesfully",__func__);
9562 } else if (audio_extn_compr_cap_enabled() &&
9563 audio_extn_compr_cap_format_supported(config->format) &&
9564 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9565 audio_extn_compr_cap_init(in);
9566 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309567 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309568 if (ret)
9569 goto err_open;
9570 } else {
9571 in->config = pcm_config_audio_capture;
9572 in->config.rate = config->sample_rate;
9573 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309574 in->format = config->format;
9575 frame_size = audio_stream_in_frame_size(&in->stream);
9576 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009577 config->format,
9578 channel_count,
9579 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009580 /* prevent division-by-zero */
9581 if (frame_size == 0) {
9582 ALOGE("%s: Error frame_size==0", __func__);
9583 ret = -EINVAL;
9584 goto err_open;
9585 }
9586
Revathi Uddarajud2634032017-12-07 14:42:34 +05309587 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009588 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009589
Revathi Uddarajud2634032017-12-07 14:42:34 +05309590 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9591 /* optionally use VOIP usecase depending on config(s) */
9592 ret = adev_update_voice_comm_input_stream(in, config);
9593 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009594
Revathi Uddarajud2634032017-12-07 14:42:34 +05309595 if (ret) {
9596 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9597 goto err_open;
9598 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009599 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309600
9601 /* assign concurrent capture usecase if record has to caried out from
9602 * actual hardware input source */
9603 if (audio_extn_is_concurrent_capture_enabled() &&
9604 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309605 /* Acquire lock to avoid two concurrent use cases initialized to
9606 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009607
Samyak Jainc37062f2019-04-25 18:41:06 +05309608 if (in->usecase == USECASE_AUDIO_RECORD) {
9609 pthread_mutex_lock(&adev->lock);
9610 if (!(adev->pcm_record_uc_state)) {
9611 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9612 adev->pcm_record_uc_state = 1;
9613 pthread_mutex_unlock(&adev->lock);
9614 } else {
9615 pthread_mutex_unlock(&adev->lock);
9616 /* Assign compress record use case for second record */
9617 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9618 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9619 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9620 if (audio_extn_cin_applicable_stream(in)) {
9621 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309622 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309623 if (ret)
9624 goto err_open;
9625 }
9626 }
9627 }
kunleiz28c73e72019-03-27 17:24:04 +08009628 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009629 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309630 if (audio_extn_ssr_get_stream() != in)
9631 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009632
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009633 in->sample_rate = in->config.rate;
9634
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309635 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9636 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009637 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009638 in->sample_rate, in->bit_width,
9639 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309640 register_format(in->format, in->supported_formats);
9641 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9642 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309643
Aalique Grahame22e49102018-12-18 14:23:57 -08009644 in->error_log = error_log_create(
9645 ERROR_LOG_ENTRIES,
9646 1000000000 /* aggregate consecutive identical errors within one second */);
9647
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009648 /* This stream could be for sound trigger lab,
9649 get sound trigger pcm if present */
9650 audio_extn_sound_trigger_check_and_get_session(in);
9651
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309652 lock_input_stream(in);
9653 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9654 pthread_mutex_lock(&adev->lock);
9655 in->card_status = adev->card_status;
9656 pthread_mutex_unlock(&adev->lock);
9657 pthread_mutex_unlock(&in->lock);
9658
Aalique Grahame22e49102018-12-18 14:23:57 -08009659 stream_app_type_cfg_init(&in->app_type_cfg);
9660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009661 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009662
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009663 ret = io_streams_map_insert(adev, &in->stream.common,
9664 handle, AUDIO_PATCH_HANDLE_NONE);
9665 if (ret != 0)
9666 goto err_open;
9667
Derek Chenf939fb72018-11-13 13:34:41 -08009668 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9669 calloc(1, sizeof(streams_input_ctxt_t));
9670 if (in_ctxt == NULL) {
9671 ALOGE("%s fail to allocate input ctxt", __func__);
9672 ret = -ENOMEM;
9673 goto err_open;
9674 }
9675 in_ctxt->input = in;
9676
9677 pthread_mutex_lock(&adev->lock);
9678 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9679 pthread_mutex_unlock(&adev->lock);
9680
Eric Laurent994a6932013-07-17 11:51:42 -07009681 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009682 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009683
9684err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309685 if (in->usecase == USECASE_AUDIO_RECORD) {
9686 pthread_mutex_lock(&adev->lock);
9687 adev->pcm_record_uc_state = 0;
9688 pthread_mutex_unlock(&adev->lock);
9689 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009690 free(in);
9691 *stream_in = NULL;
9692 return ret;
9693}
9694
9695static void adev_close_input_stream(struct audio_hw_device *dev,
9696 struct audio_stream_in *stream)
9697{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009698 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009699 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009700 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309701
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309702 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009703
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009704 if (in == NULL) {
9705 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9706 return;
9707 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009708 io_streams_map_remove(adev, in->capture_handle);
9709
kunleiz70e57612018-12-28 17:50:23 +08009710 /* must deregister from sndmonitor first to prevent races
9711 * between the callback and close_stream
9712 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309713 audio_extn_snd_mon_unregister_listener(stream);
9714
kunleiz70e57612018-12-28 17:50:23 +08009715 /* Disable echo reference if there are no active input, hfp call
9716 * and sound trigger while closing input stream
9717 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009718 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009719 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009720 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9721 struct listnode out_devices;
9722 list_init(&out_devices);
9723 platform_set_echo_reference(adev, false, &out_devices);
9724 } else
kunleiz70e57612018-12-28 17:50:23 +08009725 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309726
Weiyin Jiang2995f662019-04-17 14:25:12 +08009727 error_log_destroy(in->error_log);
9728 in->error_log = NULL;
9729
Pallavid7c7a272018-01-16 11:22:55 +05309730
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009731 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309732 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009733 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309734 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009735 if (ret != 0)
9736 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9737 __func__, ret);
9738 } else
9739 in_standby(&stream->common);
9740
Revathi Uddarajud2634032017-12-07 14:42:34 +05309741 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309742 if (in->usecase == USECASE_AUDIO_RECORD) {
9743 adev->pcm_record_uc_state = 0;
9744 }
9745
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009746 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9747 adev->enable_voicerx = false;
9748 }
9749
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009750 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009751 audio_extn_ssr_deinit();
9752 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009753
Garmond Leunge2433c32017-09-28 21:51:22 -07009754 if (audio_extn_ffv_get_stream() == in) {
9755 audio_extn_ffv_stream_deinit();
9756 }
9757
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309758 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009759 audio_extn_compr_cap_format_supported(in->config.format))
9760 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309761
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309762 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309763 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009764
Mingming Yinfd7607b2016-01-22 12:48:44 -08009765 if (in->is_st_session) {
9766 ALOGV("%s: sound trigger pcm stop lab", __func__);
9767 audio_extn_sound_trigger_stop_lab(in);
9768 }
Derek Chenf939fb72018-11-13 13:34:41 -08009769 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9770 if (in_ctxt != NULL) {
9771 list_remove(&in_ctxt->list);
9772 free(in_ctxt);
9773 } else {
9774 ALOGW("%s, input stream already closed", __func__);
9775 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009776 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309777 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009778 return;
9779}
9780
Aalique Grahame22e49102018-12-18 14:23:57 -08009781/* verifies input and output devices and their capabilities.
9782 *
9783 * This verification is required when enabling extended bit-depth or
9784 * sampling rates, as not all qcom products support it.
9785 *
9786 * Suitable for calling only on initialization such as adev_open().
9787 * It fills the audio_device use_case_table[] array.
9788 *
9789 * Has a side-effect that it needs to configure audio routing / devices
9790 * in order to power up the devices and read the device parameters.
9791 * It does not acquire any hw device lock. Should restore the devices
9792 * back to "normal state" upon completion.
9793 */
9794static int adev_verify_devices(struct audio_device *adev)
9795{
9796 /* enumeration is a bit difficult because one really wants to pull
9797 * the use_case, device id, etc from the hidden pcm_device_table[].
9798 * In this case there are the following use cases and device ids.
9799 *
9800 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9801 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9802 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9803 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9804 * [USECASE_AUDIO_RECORD] = {0, 0},
9805 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9806 * [USECASE_VOICE_CALL] = {2, 2},
9807 *
9808 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9809 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9810 */
9811
9812 /* should be the usecases enabled in adev_open_input_stream() */
9813 static const int test_in_usecases[] = {
9814 USECASE_AUDIO_RECORD,
9815 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9816 };
9817 /* should be the usecases enabled in adev_open_output_stream()*/
9818 static const int test_out_usecases[] = {
9819 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9820 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9821 };
9822 static const usecase_type_t usecase_type_by_dir[] = {
9823 PCM_PLAYBACK,
9824 PCM_CAPTURE,
9825 };
9826 static const unsigned flags_by_dir[] = {
9827 PCM_OUT,
9828 PCM_IN,
9829 };
9830
9831 size_t i;
9832 unsigned dir;
9833 const unsigned card_id = adev->snd_card;
9834
9835 for (dir = 0; dir < 2; ++dir) {
9836 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9837 const unsigned flags_dir = flags_by_dir[dir];
9838 const size_t testsize =
9839 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9840 const int *testcases =
9841 dir ? test_in_usecases : test_out_usecases;
9842 const audio_devices_t audio_device =
9843 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9844
9845 for (i = 0; i < testsize; ++i) {
9846 const audio_usecase_t audio_usecase = testcases[i];
9847 int device_id;
9848 struct pcm_params **pparams;
9849 struct stream_out out;
9850 struct stream_in in;
9851 struct audio_usecase uc_info;
9852 int retval;
9853
9854 pparams = &adev->use_case_table[audio_usecase];
9855 pcm_params_free(*pparams); /* can accept null input */
9856 *pparams = NULL;
9857
9858 /* find the device ID for the use case (signed, for error) */
9859 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9860 if (device_id < 0)
9861 continue;
9862
9863 /* prepare structures for device probing */
9864 memset(&uc_info, 0, sizeof(uc_info));
9865 uc_info.id = audio_usecase;
9866 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009867 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009868 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009869 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009870 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009871 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009872 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9873 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009874 }
9875 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009876 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009877 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009878 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009879 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009880 uc_info.in_snd_device = SND_DEVICE_NONE;
9881 uc_info.out_snd_device = SND_DEVICE_NONE;
9882 list_add_tail(&adev->usecase_list, &uc_info.list);
9883
9884 /* select device - similar to start_(in/out)put_stream() */
9885 retval = select_devices(adev, audio_usecase);
9886 if (retval >= 0) {
9887 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9888#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009889 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009890 if (*pparams) {
9891 ALOGV("%s: (%s) card %d device %d", __func__,
9892 dir ? "input" : "output", card_id, device_id);
9893 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9894 } else {
9895 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9896 }
9897#endif
9898 }
9899
9900 /* deselect device - similar to stop_(in/out)put_stream() */
9901 /* 1. Get and set stream specific mixer controls */
9902 retval = disable_audio_route(adev, &uc_info);
9903 /* 2. Disable the rx device */
9904 retval = disable_snd_device(adev,
9905 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9906 list_remove(&uc_info.list);
9907 }
9908 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009909 return 0;
9910}
9911
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009912int update_patch(unsigned int num_sources,
9913 const struct audio_port_config *sources,
9914 unsigned int num_sinks,
9915 const struct audio_port_config *sinks,
9916 audio_patch_handle_t handle,
9917 struct audio_patch_info *p_info,
9918 patch_type_t patch_type, bool new_patch)
9919{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009920 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009921
9922 if (p_info == NULL) {
9923 ALOGE("%s: Invalid patch pointer", __func__);
9924 return -EINVAL;
9925 }
9926
9927 if (new_patch) {
9928 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9929 if (p_info->patch == NULL) {
9930 ALOGE("%s: Could not allocate patch", __func__);
9931 return -ENOMEM;
9932 }
9933 }
9934
9935 p_info->patch->id = handle;
9936 p_info->patch->num_sources = num_sources;
9937 p_info->patch->num_sinks = num_sinks;
9938
9939 for (int i = 0; i < num_sources; i++)
9940 p_info->patch->sources[i] = sources[i];
9941 for (int i = 0; i < num_sinks; i++)
9942 p_info->patch->sinks[i] = sinks[i];
9943
9944 p_info->patch_type = patch_type;
9945 return 0;
9946}
9947
9948audio_patch_handle_t generate_patch_handle()
9949{
9950 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9951 if (++patch_handle < 0)
9952 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9953 return patch_handle;
9954}
9955
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309956int adev_create_audio_patch(struct audio_hw_device *dev,
9957 unsigned int num_sources,
9958 const struct audio_port_config *sources,
9959 unsigned int num_sinks,
9960 const struct audio_port_config *sinks,
9961 audio_patch_handle_t *handle)
9962{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009963 int ret = 0;
9964 struct audio_device *adev = (struct audio_device *)dev;
9965 struct audio_patch_info *p_info = NULL;
9966 patch_type_t patch_type = PATCH_NONE;
9967 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9968 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9969 struct audio_stream_info *s_info = NULL;
9970 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009971 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009972 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9973 bool new_patch = false;
9974 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309975
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009976 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9977 num_sources, num_sinks, *handle);
9978
9979 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9980 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9981 ALOGE("%s: Invalid patch arguments", __func__);
9982 ret = -EINVAL;
9983 goto done;
9984 }
9985
9986 if (num_sources > 1) {
9987 ALOGE("%s: Multiple sources are not supported", __func__);
9988 ret = -EINVAL;
9989 goto done;
9990 }
9991
9992 if (sources == NULL || sinks == NULL) {
9993 ALOGE("%s: Invalid sources or sinks port config", __func__);
9994 ret = -EINVAL;
9995 goto done;
9996 }
9997
9998 ALOGV("%s: source role %d, source type %d", __func__,
9999 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010000 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010001
10002 // Populate source/sink information and fetch stream info
10003 switch (sources[0].type) {
10004 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10005 device_type = sources[0].ext.device.type;
10006 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010007 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010008 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10009 patch_type = PATCH_CAPTURE;
10010 io_handle = sinks[0].ext.mix.handle;
10011 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010012 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010013 __func__, device_type, io_handle);
10014 } else {
10015 // Device to device patch is not implemented.
10016 // This space will need changes if audio HAL
10017 // handles device to device patches in the future.
10018 patch_type = PATCH_DEVICE_LOOPBACK;
10019 }
10020 break;
10021 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10022 io_handle = sources[0].ext.mix.handle;
10023 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010024 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010026 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010027 }
10028 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010029 ALOGD("%s: Playback patch from mix handle %d to device %x",
10030 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010031 break;
10032 case AUDIO_PORT_TYPE_SESSION:
10033 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010034 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10035 ret = -EINVAL;
10036 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037 }
10038
10039 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010040
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010041 // Generate patch info and update patch
10042 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010043 *handle = generate_patch_handle();
10044 p_info = (struct audio_patch_info *)
10045 calloc(1, sizeof(struct audio_patch_info));
10046 if (p_info == NULL) {
10047 ALOGE("%s: Failed to allocate memory", __func__);
10048 pthread_mutex_unlock(&adev->lock);
10049 ret = -ENOMEM;
10050 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010052 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010053 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010054 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010055 if (p_info == NULL) {
10056 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10057 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010058 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059 ret = -EINVAL;
10060 goto done;
10061 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010062 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010063 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010064 *handle, p_info, patch_type, new_patch);
10065
10066 // Fetch stream info of associated mix for playback or capture patches
10067 if (p_info->patch_type == PATCH_PLAYBACK ||
10068 p_info->patch_type == PATCH_CAPTURE) {
10069 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10070 if (s_info == NULL) {
10071 ALOGE("%s: Failed to obtain stream info", __func__);
10072 if (new_patch)
10073 free(p_info);
10074 pthread_mutex_unlock(&adev->lock);
10075 ret = -EINVAL;
10076 goto done;
10077 }
10078 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10079 s_info->patch_handle = *handle;
10080 stream = s_info->stream;
10081 }
10082 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083
10084 // Update routing for stream
10085 if (stream != NULL) {
10086 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010087 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010088 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010089 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010090 if (ret < 0) {
10091 pthread_mutex_lock(&adev->lock);
10092 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10093 if (new_patch)
10094 free(p_info);
10095 pthread_mutex_unlock(&adev->lock);
10096 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10097 goto done;
10098 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010099 }
10100
10101 // Add new patch to patch map
10102 if (!ret && new_patch) {
10103 pthread_mutex_lock(&adev->lock);
10104 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010106 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107 }
10108
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010109done:
10110 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010111 num_sources,
10112 sources,
10113 num_sinks,
10114 sinks,
10115 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010116 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010117 num_sources,
10118 sources,
10119 num_sinks,
10120 sinks,
10121 handle);
10122 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010123}
10124
10125int adev_release_audio_patch(struct audio_hw_device *dev,
10126 audio_patch_handle_t handle)
10127{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128 struct audio_device *adev = (struct audio_device *) dev;
10129 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010130 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010131 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010132
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010133 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10134 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10135 ret = -EINVAL;
10136 goto done;
10137 }
10138
10139 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010140 pthread_mutex_lock(&adev->lock);
10141 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010142 if (p_info == NULL) {
10143 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010144 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010145 ret = -EINVAL;
10146 goto done;
10147 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010148 struct audio_patch *patch = p_info->patch;
10149 if (patch == NULL) {
10150 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010151 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 goto done;
10154 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010155 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10156 switch (patch->sources[0].type) {
10157 case AUDIO_PORT_TYPE_MIX:
10158 io_handle = patch->sources[0].ext.mix.handle;
10159 break;
10160 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010161 if (p_info->patch_type == PATCH_CAPTURE)
10162 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010163 break;
10164 case AUDIO_PORT_TYPE_SESSION:
10165 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010166 pthread_mutex_unlock(&adev->lock);
10167 ret = -EINVAL;
10168 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 }
10170
10171 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010172 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010173 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010174 if (patch_type == PATCH_PLAYBACK ||
10175 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010176 struct audio_stream_info *s_info =
10177 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10178 if (s_info == NULL) {
10179 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10180 pthread_mutex_unlock(&adev->lock);
10181 goto done;
10182 }
10183 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10184 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010185 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010186 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010188 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010189 struct listnode devices;
10190 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010191 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010192 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010193 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010194 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195 }
10196
10197 if (ret < 0)
10198 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10199
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010200done:
10201 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10202 audio_extn_auto_hal_release_audio_patch(dev, handle);
10203
10204 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010205 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010206}
10207
10208int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10209{
Derek Chenf13dd492018-11-13 14:53:51 -080010210 int ret = 0;
10211
10212 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10213 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10214 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010215}
10216
10217int adev_set_audio_port_config(struct audio_hw_device *dev,
10218 const struct audio_port_config *config)
10219{
Derek Chenf13dd492018-11-13 14:53:51 -080010220 int ret = 0;
10221
10222 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10223 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10224 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010225}
10226
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010227static int adev_dump(const audio_hw_device_t *device __unused,
10228 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010229{
10230 return 0;
10231}
10232
10233static int adev_close(hw_device_t *device)
10234{
Aalique Grahame22e49102018-12-18 14:23:57 -080010235 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010236 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010237
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010238 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010239 return 0;
10240
10241 pthread_mutex_lock(&adev_init_lock);
10242
10243 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010244 if (audio_extn_spkr_prot_is_enabled())
10245 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010246 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010247 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010248 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010249 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010250 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010251 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010252 audio_extn_utils_release_streams_cfg_lists(
10253 &adev->streams_output_cfg_list,
10254 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010255 if (audio_extn_qap_is_enabled())
10256 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010257 if (audio_extn_qaf_is_enabled())
10258 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010259 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010260 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010261 free(adev->snd_dev_ref_cnt);
10262 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010263 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10264 pcm_params_free(adev->use_case_table[i]);
10265 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010266 if (adev->adm_deinit)
10267 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010268 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010269 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010270 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010271 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010272 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010273 if (adev->device_cfg_params) {
10274 free(adev->device_cfg_params);
10275 adev->device_cfg_params = NULL;
10276 }
Derek Chend2530072014-11-24 12:39:14 -080010277 if(adev->ext_hw_plugin)
10278 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010279 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010280 free_map(adev->patch_map);
10281 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010282 free(device);
10283 adev = NULL;
10284 }
10285 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010286 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010287 return 0;
10288}
10289
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010290/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10291 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10292 * just that it _might_ work.
10293 */
10294static int period_size_is_plausible_for_low_latency(int period_size)
10295{
10296 switch (period_size) {
10297 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010298 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010299 case 240:
10300 case 320:
10301 case 480:
10302 return 1;
10303 default:
10304 return 0;
10305 }
10306}
10307
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010308static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10309{
10310 bool is_snd_card_status = false;
10311 bool is_ext_device_status = false;
10312 char value[32];
10313 int card = -1;
10314 card_status_t status;
10315
10316 if (cookie != adev || !parms)
10317 return;
10318
10319 if (!parse_snd_card_status(parms, &card, &status)) {
10320 is_snd_card_status = true;
10321 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10322 is_ext_device_status = true;
10323 } else {
10324 // not a valid event
10325 return;
10326 }
10327
10328 pthread_mutex_lock(&adev->lock);
10329 if (card == adev->snd_card || is_ext_device_status) {
10330 if (is_snd_card_status && adev->card_status != status) {
10331 adev->card_status = status;
10332 platform_snd_card_update(adev->platform, status);
10333 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010334 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010335 if (status == CARD_STATUS_OFFLINE)
10336 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010337 } else if (is_ext_device_status) {
10338 platform_set_parameters(adev->platform, parms);
10339 }
10340 }
10341 pthread_mutex_unlock(&adev->lock);
10342 return;
10343}
10344
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010345/* out and adev lock held */
10346static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10347{
10348 struct audio_usecase *uc_info;
10349 float left_p;
10350 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010351 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010352
10353 uc_info = get_usecase_from_list(adev, out->usecase);
10354 if (uc_info == NULL) {
10355 ALOGE("%s: Could not find the usecase (%d) in the list",
10356 __func__, out->usecase);
10357 return -EINVAL;
10358 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010359 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010360
10361 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10362 out->usecase, use_case_table[out->usecase]);
10363
10364 if (restore) {
10365 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010366 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010367 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010368 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10369 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010370 pthread_mutex_lock(&out->compr_mute_lock);
10371 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010372 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010373 out->a2dp_compress_mute = false;
10374 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10375 }
10376 pthread_mutex_unlock(&out->compr_mute_lock);
10377 }
10378 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010379 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10380 // mute compress stream if suspended
10381 pthread_mutex_lock(&out->compr_mute_lock);
10382 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010383 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010384 assign_devices(&devices, &out->device_list);
10385 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010386 left_p = out->volume_l;
10387 right_p = out->volume_r;
10388 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10389 compress_pause(out->compr);
10390 out_set_compr_volume(&out->stream, (float)0, (float)0);
10391 out->a2dp_compress_mute = true;
10392 select_devices(adev, out->usecase);
10393 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10394 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010395 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010396 out->volume_l = left_p;
10397 out->volume_r = right_p;
10398 }
Zhou Songc576a452019-09-09 14:17:40 +080010399 pthread_mutex_unlock(&out->compr_mute_lock);
10400 } else {
10401 // tear down a2dp path for non offloaded streams
10402 if (audio_extn_a2dp_source_is_suspended())
10403 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010404 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010405 }
10406 ALOGV("%s: exit", __func__);
10407 return 0;
10408}
10409
10410int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10411{
10412 int ret = 0;
10413
10414 lock_output_stream(out);
10415 pthread_mutex_lock(&adev->lock);
10416
10417 ret = check_a2dp_restore_l(adev, out, restore);
10418
10419 pthread_mutex_unlock(&adev->lock);
10420 pthread_mutex_unlock(&out->lock);
10421 return ret;
10422}
10423
Haynes Mathew George01156f92018-04-13 15:29:54 -070010424void adev_on_battery_status_changed(bool charging)
10425{
10426 pthread_mutex_lock(&adev->lock);
10427 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10428 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010429 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010430 pthread_mutex_unlock(&adev->lock);
10431}
10432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010433static int adev_open(const hw_module_t *module, const char *name,
10434 hw_device_t **device)
10435{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010436 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010437 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010438 char mixer_ctl_name[128] = {0};
10439 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010440
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010441 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010442 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10443
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010444 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010445 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010446 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010447 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010448 ALOGD("%s: returning existing instance of adev", __func__);
10449 ALOGD("%s: exit", __func__);
10450 pthread_mutex_unlock(&adev_init_lock);
10451 return 0;
10452 }
10453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010454 adev = calloc(1, sizeof(struct audio_device));
10455
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010456 if (!adev) {
10457 pthread_mutex_unlock(&adev_init_lock);
10458 return -ENOMEM;
10459 }
10460
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010461 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10462
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010463 // register audio ext hidl at the earliest
10464 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010465#ifdef DYNAMIC_LOG_ENABLED
10466 register_for_dynamic_logging("hal");
10467#endif
10468
Derek Chenf939fb72018-11-13 13:34:41 -080010469 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010470 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010471 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10472 maj_version = atoi(value);
10473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010474 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010475 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010476 adev->device.common.module = (struct hw_module_t *)module;
10477 adev->device.common.close = adev_close;
10478
10479 adev->device.init_check = adev_init_check;
10480 adev->device.set_voice_volume = adev_set_voice_volume;
10481 adev->device.set_master_volume = adev_set_master_volume;
10482 adev->device.get_master_volume = adev_get_master_volume;
10483 adev->device.set_master_mute = adev_set_master_mute;
10484 adev->device.get_master_mute = adev_get_master_mute;
10485 adev->device.set_mode = adev_set_mode;
10486 adev->device.set_mic_mute = adev_set_mic_mute;
10487 adev->device.get_mic_mute = adev_get_mic_mute;
10488 adev->device.set_parameters = adev_set_parameters;
10489 adev->device.get_parameters = adev_get_parameters;
10490 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10491 adev->device.open_output_stream = adev_open_output_stream;
10492 adev->device.close_output_stream = adev_close_output_stream;
10493 adev->device.open_input_stream = adev_open_input_stream;
10494 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010495 adev->device.create_audio_patch = adev_create_audio_patch;
10496 adev->device.release_audio_patch = adev_release_audio_patch;
10497 adev->device.get_audio_port = adev_get_audio_port;
10498 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010499 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010500 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010501
10502 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010503 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010504 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010505 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010506 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010507 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010508 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010509 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010510 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010511 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010512 /* Init audio and voice feature */
10513 audio_extn_feature_init();
10514 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010515 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010516 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010517 list_init(&adev->active_inputs_list);
10518 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010519 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010520 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10521 audio_extn_utils_hash_eq);
10522 if (!adev->io_streams_map) {
10523 ALOGE("%s: Could not create io streams map", __func__);
10524 ret = -ENOMEM;
10525 goto adev_open_err;
10526 }
10527 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10528 audio_extn_utils_hash_eq);
10529 if (!adev->patch_map) {
10530 ALOGE("%s: Could not create audio patch map", __func__);
10531 ret = -ENOMEM;
10532 goto adev_open_err;
10533 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010534 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010535 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010536 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010537 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010538 adev->perf_lock_opts[0] = 0x101;
10539 adev->perf_lock_opts[1] = 0x20E;
10540 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010541 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010542 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010543 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010544 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010545 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010546
Zhou Song68ebc352019-12-05 17:11:15 +080010547 audio_extn_perf_lock_init();
10548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010549 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010550 adev->platform = platform_init(adev);
10551 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010552 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010553 ret = -EINVAL;
10554 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010555 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010556
Aalique Grahame22e49102018-12-18 14:23:57 -080010557 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010558 if (audio_extn_qap_is_enabled()) {
10559 ret = audio_extn_qap_init(adev);
10560 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010561 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010562 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010563 }
10564 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10565 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10566 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010567
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010568 if (audio_extn_qaf_is_enabled()) {
10569 ret = audio_extn_qaf_init(adev);
10570 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010571 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010572 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010573 }
10574
10575 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10576 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10577 }
10578
Derek Chenae7b0342019-02-08 15:17:04 -080010579 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010580 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10581
Eric Laurentc4aef752013-09-12 17:45:53 -070010582 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10583 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10584 if (adev->visualizer_lib == NULL) {
10585 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10586 } else {
10587 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10588 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010589 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010590 "visualizer_hal_start_output");
10591 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010592 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010593 "visualizer_hal_stop_output");
10594 }
10595 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010596 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010597 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010598 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010599 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010600 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010601 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010602
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010603 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10604 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10605 if (adev->offload_effects_lib == NULL) {
10606 ALOGE("%s: DLOPEN failed for %s", __func__,
10607 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10608 } else {
10609 ALOGV("%s: DLOPEN successful for %s", __func__,
10610 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10611 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010612 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010613 "offload_effects_bundle_hal_start_output");
10614 adev->offload_effects_stop_output =
10615 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10616 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010617 adev->offload_effects_set_hpx_state =
10618 (int (*)(bool))dlsym(adev->offload_effects_lib,
10619 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010620 adev->offload_effects_get_parameters =
10621 (void (*)(struct str_parms *, struct str_parms *))
10622 dlsym(adev->offload_effects_lib,
10623 "offload_effects_bundle_get_parameters");
10624 adev->offload_effects_set_parameters =
10625 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10626 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010627 }
10628 }
10629
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010630 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10631 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10632 if (adev->adm_lib == NULL) {
10633 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10634 } else {
10635 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10636 adev->adm_init = (adm_init_t)
10637 dlsym(adev->adm_lib, "adm_init");
10638 adev->adm_deinit = (adm_deinit_t)
10639 dlsym(adev->adm_lib, "adm_deinit");
10640 adev->adm_register_input_stream = (adm_register_input_stream_t)
10641 dlsym(adev->adm_lib, "adm_register_input_stream");
10642 adev->adm_register_output_stream = (adm_register_output_stream_t)
10643 dlsym(adev->adm_lib, "adm_register_output_stream");
10644 adev->adm_deregister_stream = (adm_deregister_stream_t)
10645 dlsym(adev->adm_lib, "adm_deregister_stream");
10646 adev->adm_request_focus = (adm_request_focus_t)
10647 dlsym(adev->adm_lib, "adm_request_focus");
10648 adev->adm_abandon_focus = (adm_abandon_focus_t)
10649 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010650 adev->adm_set_config = (adm_set_config_t)
10651 dlsym(adev->adm_lib, "adm_set_config");
10652 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10653 dlsym(adev->adm_lib, "adm_request_focus_v2");
10654 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10655 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10656 adev->adm_on_routing_change = (adm_on_routing_change_t)
10657 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010658 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10659 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010660 }
10661 }
10662
Aalique Grahame22e49102018-12-18 14:23:57 -080010663 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010664 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010665 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010666 //initialize this to false for now,
10667 //this will be set to true through set param
10668 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010669
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010670 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010671 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010672
10673 if (k_enable_extended_precision)
10674 adev_verify_devices(adev);
10675
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010676 adev->dsp_bit_width_enforce_mode =
10677 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010678
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010679 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10680 &adev->streams_output_cfg_list,
10681 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010682
Kiran Kandi910e1862013-10-29 13:29:42 -070010683 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010684
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010685 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010686 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010687 trial = atoi(value);
10688 if (period_size_is_plausible_for_low_latency(trial)) {
10689 pcm_config_low_latency.period_size = trial;
10690 pcm_config_low_latency.start_threshold = trial / 4;
10691 pcm_config_low_latency.avail_min = trial / 4;
10692 configured_low_latency_capture_period_size = trial;
10693 }
10694 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010695 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10696 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010697 trial = atoi(value);
10698 if (period_size_is_plausible_for_low_latency(trial)) {
10699 configured_low_latency_capture_period_size = trial;
10700 }
10701 }
10702
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010703 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10704
Eric Laurent4b084132018-10-19 17:33:43 -070010705 adev->camera_orientation = CAMERA_DEFAULT;
10706
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010707 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010708 af_period_multiplier = atoi(value);
10709 if (af_period_multiplier < 0)
10710 af_period_multiplier = 2;
10711 else if (af_period_multiplier > 4)
10712 af_period_multiplier = 4;
10713
10714 ALOGV("new period_multiplier = %d", af_period_multiplier);
10715 }
10716
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010717 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010718
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010719 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010720 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010721 pthread_mutex_unlock(&adev_init_lock);
10722
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010723 if (adev->adm_init)
10724 adev->adm_data = adev->adm_init();
10725
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010726 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010727 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010728
10729 audio_extn_snd_mon_init();
10730 pthread_mutex_lock(&adev->lock);
10731 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10732 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010733 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10734 /*
10735 * if the battery state callback happens before charging can be queried,
10736 * it will be guarded with the adev->lock held in the cb function and so
10737 * the callback value will reflect the latest state
10738 */
10739 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010740 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010741 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010742 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010743 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010744 /* Allocate memory for Device config params */
10745 adev->device_cfg_params = (struct audio_device_config_param*)
10746 calloc(platform_get_max_codec_backend(),
10747 sizeof(struct audio_device_config_param));
10748 if (adev->device_cfg_params == NULL)
10749 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010750
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010751 /*
10752 * Check if new PSPD matrix mixer control is supported. If not
10753 * supported, then set flag so that old mixer ctrl is sent while
10754 * sending pspd coefficients on older kernel version. Query mixer
10755 * control for default pcm id and channel value one.
10756 */
10757 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10758 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10759
10760 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10761 if (!ctl) {
10762 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10763 __func__, mixer_ctl_name);
10764 adev->use_old_pspd_mix_ctrl = true;
10765 }
10766
Eric Laurent994a6932013-07-17 11:51:42 -070010767 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010768 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010769
10770adev_open_err:
10771 free_map(adev->patch_map);
10772 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010773 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010774 pthread_mutex_destroy(&adev->lock);
10775 free(adev);
10776 adev = NULL;
10777 *device = NULL;
10778 pthread_mutex_unlock(&adev_init_lock);
10779 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010780}
10781
10782static struct hw_module_methods_t hal_module_methods = {
10783 .open = adev_open,
10784};
10785
10786struct audio_module HAL_MODULE_INFO_SYM = {
10787 .common = {
10788 .tag = HARDWARE_MODULE_TAG,
10789 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10790 .hal_api_version = HARDWARE_HAL_API_VERSION,
10791 .id = AUDIO_HARDWARE_MODULE_ID,
10792 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010793 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010794 .methods = &hal_module_methods,
10795 },
10796};