blob: 174d314dc543a945924be2156dfd3cb26afdb896 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530402 /* For Interactive Audio Streams */
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700411
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800412 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
413
Derek Chenf6318be2017-06-12 17:16:24 -0400414 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
415
416 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
417 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
418 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
419 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800420 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700421 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530422 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700423};
424
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700425static const audio_usecase_t offload_usecases[] = {
426 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700435};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436
Varun Balaraje49253e2017-07-06 19:48:56 +0530437static const audio_usecase_t interactive_usecases[] = {
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
446};
447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448#define STRING_TO_ENUM(string) { #string, string }
449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450struct string_to_enum {
451 const char *name;
452 uint32_t value;
453};
454
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800475};
476
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700477static const struct string_to_enum formats_name_to_enum_table[] = {
478 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700481 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
482 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700484 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800485 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
486 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700487 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800488};
489
490//list of all supported sample rates by HDMI specification.
491static const int out_hdmi_sample_rates[] = {
492 32000, 44100, 48000, 88200, 96000, 176400, 192000,
493};
494
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700495static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800496 STRING_TO_ENUM(32000),
497 STRING_TO_ENUM(44100),
498 STRING_TO_ENUM(48000),
499 STRING_TO_ENUM(88200),
500 STRING_TO_ENUM(96000),
501 STRING_TO_ENUM(176400),
502 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800503 STRING_TO_ENUM(352800),
504 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700505};
506
Carter Hsu2e429db2019-05-14 18:50:52 +0800507struct in_effect_list {
508 struct listnode list;
509 effect_handle_t handle;
510};
511
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700512static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700513static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700514static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700515//cache last MBDRC cal step level
516static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700517
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700519static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800520static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530521static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530522
Derek Chen6f293672019-04-01 01:40:24 -0700523static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
524static void in_snd_mon_cb(void * stream, struct str_parms * parms);
525static void out_snd_mon_cb(void * stream, struct str_parms * parms);
526
Zhou Song331c8e52019-08-26 14:16:12 +0800527static int configure_btsco_sample_rate(snd_device_t snd_device);
528
Vatsal Buchac09ae062018-11-14 13:25:08 +0530529#ifdef AUDIO_FEATURE_ENABLED_GCOV
530extern void __gcov_flush();
531static void enable_gcov()
532{
533 __gcov_flush();
534}
535#else
536static void enable_gcov()
537{
538}
539#endif
540
justinweng20fb6d82019-02-21 18:49:00 -0700541static int in_set_microphone_direction(const struct audio_stream_in *stream,
542 audio_microphone_direction_t dir);
543static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
544
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700545static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
546 int flags __unused)
547{
548 int dir = 0;
549 switch (uc_id) {
550 case USECASE_AUDIO_RECORD_LOW_LATENCY:
551 dir = 1;
552 case USECASE_AUDIO_PLAYBACK_ULL:
553 break;
554 default:
555 return false;
556 }
557
558 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
559 PCM_PLAYBACK : PCM_CAPTURE);
560 if (adev->adm_is_noirq_avail)
561 return adev->adm_is_noirq_avail(adev->adm_data,
562 adev->snd_card, dev_id, dir);
563 return false;
564}
565
566static void register_out_stream(struct stream_out *out)
567{
568 struct audio_device *adev = out->dev;
569 if (is_offload_usecase(out->usecase) ||
570 !adev->adm_register_output_stream)
571 return;
572
573 // register stream first for backward compatibility
574 adev->adm_register_output_stream(adev->adm_data,
575 out->handle,
576 out->flags);
577
578 if (!adev->adm_set_config)
579 return;
580
581 if (out->realtime)
582 adev->adm_set_config(adev->adm_data,
583 out->handle,
584 out->pcm, &out->config);
585}
586
587static void register_in_stream(struct stream_in *in)
588{
589 struct audio_device *adev = in->dev;
590 if (!adev->adm_register_input_stream)
591 return;
592
593 adev->adm_register_input_stream(adev->adm_data,
594 in->capture_handle,
595 in->flags);
596
597 if (!adev->adm_set_config)
598 return;
599
600 if (in->realtime)
601 adev->adm_set_config(adev->adm_data,
602 in->capture_handle,
603 in->pcm,
604 &in->config);
605}
606
607static void request_out_focus(struct stream_out *out, long ns)
608{
609 struct audio_device *adev = out->dev;
610
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611 if (adev->adm_request_focus_v2)
612 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
613 else if (adev->adm_request_focus)
614 adev->adm_request_focus(adev->adm_data, out->handle);
615}
616
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700617static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618{
619 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700622 if (adev->adm_request_focus_v2_1)
623 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
624 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700625 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
626 else if (adev->adm_request_focus)
627 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700628
629 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700630}
631
632static void release_out_focus(struct stream_out *out)
633{
634 struct audio_device *adev = out->dev;
635
636 if (adev->adm_abandon_focus)
637 adev->adm_abandon_focus(adev->adm_data, out->handle);
638}
639
640static void release_in_focus(struct stream_in *in)
641{
642 struct audio_device *adev = in->dev;
643 if (adev->adm_abandon_focus)
644 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
645}
646
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530647static int parse_snd_card_status(struct str_parms *parms, int *card,
648 card_status_t *status)
649{
650 char value[32]={0};
651 char state[32]={0};
652
653 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
654 if (ret < 0)
655 return -1;
656
657 // sscanf should be okay as value is of max length 32.
658 // same as sizeof state.
659 if (sscanf(value, "%d,%s", card, state) < 2)
660 return -1;
661
662 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
663 CARD_STATUS_OFFLINE;
664 return 0;
665}
666
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700667static inline void adjust_frames_for_device_delay(struct stream_out *out,
668 uint32_t *dsp_frames) {
669 // Adjustment accounts for A2dp encoder latency with offload usecases
670 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800671 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700672 unsigned long offset =
673 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
674 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
675 }
676}
677
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700678static inline bool free_entry(void *key __unused,
679 void *value, void *context __unused)
680{
681 free(value);
682 return true;
683}
684
685static inline void free_map(Hashmap *map)
686{
687 if (map) {
688 hashmapForEach(map, free_entry, (void *) NULL);
689 hashmapFree(map);
690 }
691}
692
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800693static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700694 audio_patch_handle_t patch_handle)
695{
696 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
697 return;
698
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699 struct audio_patch_info *p_info =
700 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
701 if (p_info) {
702 ALOGV("%s: Remove patch %d", __func__, patch_handle);
703 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
704 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700705 free(p_info);
706 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700707}
708
709static inline int io_streams_map_insert(struct audio_device *adev,
710 struct audio_stream *stream,
711 audio_io_handle_t handle,
712 audio_patch_handle_t patch_handle)
713{
714 struct audio_stream_info *s_info =
715 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
716
717 if (s_info == NULL) {
718 ALOGE("%s: Could not allocate stream info", __func__);
719 return -ENOMEM;
720 }
721 s_info->stream = stream;
722 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723
724 pthread_mutex_lock(&adev->lock);
725 struct audio_stream_info *stream_info =
726 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700727 if (stream_info != NULL)
728 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800729 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
731 return 0;
732}
733
734static inline void io_streams_map_remove(struct audio_device *adev,
735 audio_io_handle_t handle)
736{
737 pthread_mutex_lock(&adev->lock);
738 struct audio_stream_info *s_info =
739 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700742 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800743 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700744 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800745done:
746 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 return;
748}
749
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800750static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700751 audio_patch_handle_t handle)
752{
753 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 p_info = (struct audio_patch_info *)
755 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700756 return p_info;
757}
758
vivek mehtaa76401a2015-04-24 14:12:15 -0700759__attribute__ ((visibility ("default")))
760bool audio_hw_send_gain_dep_calibration(int level) {
761 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700762 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700763
764 pthread_mutex_lock(&adev_init_lock);
765
766 if (adev != NULL && adev->platform != NULL) {
767 pthread_mutex_lock(&adev->lock);
768 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530770 // cache level info for any of the use case which
771 // was not started.
772 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700773
vivek mehtaa76401a2015-04-24 14:12:15 -0700774 pthread_mutex_unlock(&adev->lock);
775 } else {
776 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
777 }
778
779 pthread_mutex_unlock(&adev_init_lock);
780
781 return ret_val;
782}
783
Ashish Jain5106d362016-05-11 19:23:33 +0530784static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
785{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800786 bool gapless_enabled = false;
787 const char *mixer_ctl_name = "Compress Gapless Playback";
788 struct mixer_ctl *ctl;
789
790 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700791 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530792
793 /*Disable gapless if its AV playback*/
794 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800795
796 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
797 if (!ctl) {
798 ALOGE("%s: Could not get ctl for mixer cmd - %s",
799 __func__, mixer_ctl_name);
800 return -EINVAL;
801 }
802
803 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
804 ALOGE("%s: Could not set gapless mode %d",
805 __func__, gapless_enabled);
806 return -EINVAL;
807 }
808 return 0;
809}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700810
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700811__attribute__ ((visibility ("default")))
812int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
813 int table_size) {
814 int ret_val = 0;
815 ALOGV("%s: enter ... ", __func__);
816
817 pthread_mutex_lock(&adev_init_lock);
818 if (adev == NULL) {
819 ALOGW("%s: adev is NULL .... ", __func__);
820 goto done;
821 }
822
823 pthread_mutex_lock(&adev->lock);
824 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
825 pthread_mutex_unlock(&adev->lock);
826done:
827 pthread_mutex_unlock(&adev_init_lock);
828 ALOGV("%s: exit ... ", __func__);
829 return ret_val;
830}
831
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800832bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800833{
834 bool ret = false;
835 ALOGV("%s: enter ...", __func__);
836
837 pthread_mutex_lock(&adev_init_lock);
838
839 if (adev != NULL && adev->platform != NULL) {
840 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800841 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800842 pthread_mutex_unlock(&adev->lock);
843 }
844
845 pthread_mutex_unlock(&adev_init_lock);
846
847 ALOGV("%s: exit with ret %d", __func__, ret);
848 return ret;
849}
Aalique Grahame22e49102018-12-18 14:23:57 -0800850
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700851static bool is_supported_format(audio_format_t format)
852{
Eric Laurent86e17132013-09-12 17:49:30 -0700853 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530854 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530855 format == AUDIO_FORMAT_AAC_LC ||
856 format == AUDIO_FORMAT_AAC_HE_V1 ||
857 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530858 format == AUDIO_FORMAT_AAC_ADTS_LC ||
859 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530861 format == AUDIO_FORMAT_AAC_LATM_LC ||
862 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530864 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
865 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530866 format == AUDIO_FORMAT_PCM_FLOAT ||
867 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700868 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530869 format == AUDIO_FORMAT_AC3 ||
870 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700871 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530872 format == AUDIO_FORMAT_DTS ||
873 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800874 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530875 format == AUDIO_FORMAT_ALAC ||
876 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530877 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530878 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800879 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530880 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700881 format == AUDIO_FORMAT_APTX ||
882 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800883 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700884
885 return false;
886}
887
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888static inline bool is_mmap_usecase(audio_usecase_t uc_id)
889{
890 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800891 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700892 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
893}
894
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700895static inline bool is_valid_volume(float left, float right)
896{
897 return ((left >= 0.0f && right >= 0.0f) ? true : false);
898}
899
Avinash Vaish71a8b972014-07-24 15:36:33 +0530900static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
901 struct audio_usecase *uc_info)
902{
903 struct listnode *node;
904 struct audio_usecase *usecase;
905
906 if (uc_info == NULL)
907 return -EINVAL;
908
909 /* Re-route all voice usecases on the shared backend other than the
910 specified usecase to new snd devices */
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800913 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530914 enable_audio_route(adev, usecase);
915 }
916 return 0;
917}
918
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530919static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530920{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530921 ALOGV("%s", __func__);
922 audio_route_apply_and_update_path(adev->audio_route,
923 "asrc-mode");
924 adev->asrc_mode_enabled = true;
925}
926
927static void disable_asrc_mode(struct audio_device *adev)
928{
929 ALOGV("%s", __func__);
930 audio_route_reset_and_update_path(adev->audio_route,
931 "asrc-mode");
932 adev->asrc_mode_enabled = false;
933}
934
935/*
936 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
937 * 44.1 or Native DSD backends are enabled for any of current use case.
938 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
939 * - Disable current mix path use case(Headphone backend) and re-enable it with
940 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
941 * e.g. Naitve DSD or Headphone 44.1 -> + 48
942 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530943static void check_and_set_asrc_mode(struct audio_device *adev,
944 struct audio_usecase *uc_info,
945 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530946{
947 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530948 int i, num_new_devices = 0;
949 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
950 /*
951 *Split snd device for new combo use case
952 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
953 */
954 if (platform_split_snd_device(adev->platform,
955 snd_device,
956 &num_new_devices,
957 split_new_snd_devices) == 0) {
958 for (i = 0; i < num_new_devices; i++)
959 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
960 } else {
961 int new_backend_idx = platform_get_backend_index(snd_device);
962 if (((new_backend_idx == HEADPHONE_BACKEND) ||
963 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
964 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
965 !adev->asrc_mode_enabled) {
966 struct listnode *node = NULL;
967 struct audio_usecase *uc = NULL;
968 struct stream_out *curr_out = NULL;
969 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
970 int i, num_devices, ret = 0;
971 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530972
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530973 list_for_each(node, &adev->usecase_list) {
974 uc = node_to_item(node, struct audio_usecase, list);
975 curr_out = (struct stream_out*) uc->stream.out;
976 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
977 /*
978 *Split snd device for existing combo use case
979 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
980 */
981 ret = platform_split_snd_device(adev->platform,
982 uc->out_snd_device,
983 &num_devices,
984 split_snd_devices);
985 if (ret < 0 || num_devices == 0) {
986 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
987 split_snd_devices[0] = uc->out_snd_device;
988 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800989 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530990 for (i = 0; i < num_devices; i++) {
991 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
992 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
993 if((new_backend_idx == HEADPHONE_BACKEND) &&
994 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
995 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
996 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
997 __func__);
998 enable_asrc_mode(adev);
999 break;
1000 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1001 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1002 (usecase_backend_idx == HEADPHONE_BACKEND)) {
1003 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1004 __func__);
1005 disable_audio_route(adev, uc);
1006 disable_snd_device(adev, uc->out_snd_device);
1007 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1008 if (new_backend_idx == DSD_NATIVE_BACKEND)
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-true-highquality-mode");
1011 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1012 (curr_out->bit_width >= 24))
1013 audio_route_apply_and_update_path(adev->audio_route,
1014 "hph-highquality-mode");
1015 enable_asrc_mode(adev);
1016 enable_snd_device(adev, uc->out_snd_device);
1017 enable_audio_route(adev, uc);
1018 break;
1019 }
1020 }
1021 // reset split devices count
1022 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001023 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301024 if (adev->asrc_mode_enabled)
1025 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301026 }
1027 }
1028 }
1029}
1030
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1032 struct audio_effect_config effect_config,
1033 unsigned int param_value)
1034{
1035 char mixer_ctl_name[] = "Audio Effect";
1036 struct mixer_ctl *ctl;
1037 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001038 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001039
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001040 if (in == NULL) {
1041 ALOGE("%s: active input stream is NULL", __func__);
1042 return -EINVAL;
1043 }
1044
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001045 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1046 if (!ctl) {
1047 ALOGE("%s: Could not get mixer ctl - %s",
1048 __func__, mixer_ctl_name);
1049 return -EINVAL;
1050 }
1051
1052 set_values[0] = 1; //0:Rx 1:Tx
1053 set_values[1] = in->app_type_cfg.app_type;
1054 set_values[2] = (long)effect_config.module_id;
1055 set_values[3] = (long)effect_config.instance_id;
1056 set_values[4] = (long)effect_config.param_id;
1057 set_values[5] = param_value;
1058
1059 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1060
1061 return 0;
1062
1063}
1064
1065static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1066 int effect_type, unsigned int *param_value)
1067{
1068 int ret = 0;
1069 struct audio_effect_config other_effect_config;
1070 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001071 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001072
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001073 if (in == NULL) {
1074 ALOGE("%s: active input stream is NULL", __func__);
1075 return -EINVAL;
1076 }
1077
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001078 usecase = get_usecase_from_list(adev, in->usecase);
1079 if (!usecase)
1080 return -EINVAL;
1081
1082 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1083 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1084 if (ret < 0) {
1085 ALOGE("%s Failed to get effect params %d", __func__, ret);
1086 return ret;
1087 }
1088
1089 if (module_id == other_effect_config.module_id) {
1090 //Same module id for AEC/NS. Values need to be combined
1091 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1092 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1093 *param_value |= other_effect_config.param_value;
1094 }
1095 }
1096
1097 return ret;
1098}
1099
1100static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301101{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 struct audio_effect_config effect_config;
1103 struct audio_usecase *usecase = NULL;
1104 int ret = 0;
1105 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001106 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001108 if(!voice_extn_is_dynamic_ecns_enabled())
1109 return ENOSYS;
1110
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001111 if (!in) {
1112 ALOGE("%s: Invalid input stream", __func__);
1113 return -EINVAL;
1114 }
1115
1116 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1117
1118 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001119 if (usecase == NULL) {
1120 ALOGE("%s: Could not find the usecase (%d) in the list",
1121 __func__, in->usecase);
1122 return -EINVAL;
1123 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001124
1125 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1126 if (ret < 0) {
1127 ALOGE("%s Failed to get module id %d", __func__, ret);
1128 return ret;
1129 }
1130 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1131 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1132
1133 if(enable)
1134 param_value = effect_config.param_value;
1135
1136 /*Special handling for AEC & NS effects Param values need to be
1137 updated if module ids are same*/
1138
1139 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1140 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1141 if (ret < 0)
1142 return ret;
1143 }
1144
1145 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1146
1147 return ret;
1148}
1149
1150static void check_and_enable_effect(struct audio_device *adev)
1151{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001152 if(!voice_extn_is_dynamic_ecns_enabled())
1153 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001154
Eric Laurent637e2d42018-11-15 12:24:31 -08001155 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156
Eric Laurent637e2d42018-11-15 12:24:31 -08001157 if (in != NULL && !in->standby) {
1158 if (in->enable_aec)
1159 enable_disable_effect(adev, EFFECT_AEC, true);
1160
1161 if (in->enable_ns &&
1162 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1163 enable_disable_effect(adev, EFFECT_NS, true);
1164 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001165 }
1166}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001167
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001168int pcm_ioctl(struct pcm *pcm, int request, ...)
1169{
1170 va_list ap;
1171 void * arg;
1172 int pcm_fd = *(int*)pcm;
1173
1174 va_start(ap, request);
1175 arg = va_arg(ap, void *);
1176 va_end(ap);
1177
1178 return ioctl(pcm_fd, request, arg);
1179}
1180
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001181int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001182 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001185 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301186 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301187 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001188 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301189 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001190
1191 if (usecase == NULL)
1192 return -EINVAL;
1193
1194 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1195
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 if (usecase->type == PCM_CAPTURE) {
1197 struct stream_in *in = usecase->stream.in;
1198 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001200
1201 if (in) {
1202 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001203 list_init(&out_devices);
1204 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001205 struct listnode *node;
1206 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1207 USECASE_AUDIO_PLAYBACK_VOIP);
1208 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else if (adev->primary_output &&
1212 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001213 assign_devices(&out_devices,
1214 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001215 } else {
1216 list_for_each(node, &adev->usecase_list) {
1217 uinfo = node_to_item(node, struct audio_usecase, list);
1218 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001219 assign_devices(&out_devices,
1220 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001221 break;
1222 }
1223 }
1224 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001225
1226 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 in->ec_opened = true;
1228 }
1229 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001230 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1231 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1232 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001233 snd_device = usecase->in_snd_device;
1234 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001235 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001237
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001238#ifdef DS1_DOLBY_DAP_ENABLED
1239 audio_extn_dolby_set_dmid(adev);
1240 audio_extn_dolby_set_endpoint(adev);
1241#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001242 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001243 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301244 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001245 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001246 if (audio_extn_is_maxx_audio_enabled())
1247 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301248 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301249 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1250 out = usecase->stream.out;
1251 if (out && out->compr)
1252 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1253 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254
1255 if (usecase->type == PCM_CAPTURE) {
1256 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001257 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301258 ALOGD("%s: set custom mtmx params v1", __func__);
1259 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1260 }
1261 } else {
1262 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1263 }
Manish Dewangan58229382017-02-02 15:48:41 +05301264
Andy Hung756ecc12018-10-19 17:47:12 -07001265 // we shouldn't truncate mixer_path
1266 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1267 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1268 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001269 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001270 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301271 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1272 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1273 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1274 if (parms) {
1275 audio_extn_fm_set_parameters(adev, parms);
1276 str_parms_destroy(parms);
1277 }
1278 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 ALOGV("%s: exit", __func__);
1280 return 0;
1281}
1282
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001284 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001287 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301288 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001289
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301290 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001291 return -EINVAL;
1292
1293 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301294 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 snd_device = usecase->in_snd_device;
1296 else
1297 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001298
1299 /* disable island and power mode on supported device for voice call */
1300 if (usecase->type == VOICE_CALL) {
1301 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1302 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1303 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1304 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1305 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1306 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1307 ALOGD("%s: disable island cfg and power mode in voice tx path",
1308 __func__);
1309 }
1310 }
1311 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1312 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1313 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1314 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1315 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1316 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1317 ALOGD("%s: disable island cfg and power mode in voice rx path",
1318 __func__);
1319 }
1320 }
1321 }
1322
Andy Hung756ecc12018-10-19 17:47:12 -07001323 // we shouldn't truncate mixer_path
1324 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1325 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1326 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001327 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001328 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001329 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001330 if (usecase->type == PCM_CAPTURE) {
1331 struct stream_in *in = usecase->stream.in;
1332 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001333 struct listnode out_devices;
1334 list_init(&out_devices);
1335 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001336 in->ec_opened = false;
1337 }
1338 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001339 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301340 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341
1342 if (usecase->type == PCM_CAPTURE) {
1343 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001344 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301345 ALOGD("%s: reset custom mtmx params v1", __func__);
1346 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1347 }
1348 } else {
1349 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1350 }
1351
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001352 if ((usecase->type == PCM_PLAYBACK) &&
1353 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301354 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 ALOGV("%s: exit", __func__);
1357 return 0;
1358}
1359
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001360int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001361 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001362{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301363 int i, num_devices = 0;
1364 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001365 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1366
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001367 if (snd_device < SND_DEVICE_MIN ||
1368 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001369 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001370 return -EINVAL;
1371 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001374 ALOGE("%s: Invalid sound device returned", __func__);
1375 return -EINVAL;
1376 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001377
1378 adev->snd_dev_ref_cnt[snd_device]++;
1379
1380 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1381 (platform_split_snd_device(adev->platform,
1382 snd_device,
1383 &num_devices,
1384 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001385 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001386 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001387 return 0;
1388 }
1389
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001390 if (audio_extn_spkr_prot_is_enabled())
1391 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001392
Aalique Grahame22e49102018-12-18 14:23:57 -08001393 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1394
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001395 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1396 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001397 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1398 goto err;
1399 }
1400 audio_extn_dev_arbi_acquire(snd_device);
1401 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001402 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001403 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001404 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001405 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001406 } else if (platform_split_snd_device(adev->platform,
1407 snd_device,
1408 &num_devices,
1409 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301410 for (i = 0; i < num_devices; i++) {
1411 enable_snd_device(adev, new_snd_devices[i]);
1412 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001413 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001414 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001415 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301416
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001417 /* enable island and power mode on supported device */
1418 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1419 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1420 platform_set_island_cfg_on_device(adev, snd_device, true);
1421 platform_set_power_mode_on_device(adev, snd_device, true);
1422 ALOGD("%s: enable island cfg and power mode on: %s",
1423 __func__, device_name);
1424 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301425
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301426 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1427 if (audio_extn_a2dp_start_playback() < 0) {
1428 ALOGE(" fail to configure A2dp Source control path ");
1429 goto err;
1430 } else {
1431 adev->a2dp_started = true;
1432 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001433 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001434
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001435 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1436 (audio_extn_a2dp_start_capture() < 0)) {
1437 ALOGE(" fail to configure A2dp Sink control path ");
1438 goto err;
1439 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301440
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001441 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1442 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1443 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1444 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1445 ALOGE(" fail to configure sco control path ");
1446 goto err;
1447 }
Zhou Song12c29502019-03-16 10:37:18 +08001448 }
1449
Zhou Song331c8e52019-08-26 14:16:12 +08001450 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001451 /* due to the possibility of calibration overwrite between listen
1452 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001453 audio_extn_sound_trigger_update_device_status(snd_device,
1454 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301455 audio_extn_listen_update_device_status(snd_device,
1456 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001457 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001458 audio_extn_sound_trigger_update_device_status(snd_device,
1459 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301460 audio_extn_listen_update_device_status(snd_device,
1461 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001462 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001463 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001464 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001465 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301466
1467 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1468 !adev->native_playback_enabled &&
1469 audio_is_true_native_stream_active(adev)) {
1470 ALOGD("%s: %d: napb: enabling native mode in hardware",
1471 __func__, __LINE__);
1472 audio_route_apply_and_update_path(adev->audio_route,
1473 "true-native-mode");
1474 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301475 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301476 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1477 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001478 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001479 ALOGD("%s: init ec ref loopback", __func__);
1480 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001484err:
1485 adev->snd_dev_ref_cnt[snd_device]--;
1486 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487}
1488
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001489int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001490 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301492 int i, num_devices = 0;
1493 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001494 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1495
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001496 if (snd_device < SND_DEVICE_MIN ||
1497 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001498 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001499 return -EINVAL;
1500 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501
1502 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1503 ALOGE("%s: Invalid sound device returned", __func__);
1504 return -EINVAL;
1505 }
1506
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1508 ALOGE("%s: device ref cnt is already 0", __func__);
1509 return -EINVAL;
1510 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001511
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001512 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001513
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001514
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001516 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301517
Aalique Grahame22e49102018-12-18 14:23:57 -08001518 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1519
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001520 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1521 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001522 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001523
1524 // when speaker device is disabled, reset swap.
1525 // will be renabled on usecase start
1526 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001527 } else if (platform_split_snd_device(adev->platform,
1528 snd_device,
1529 &num_devices,
1530 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301531 for (i = 0; i < num_devices; i++) {
1532 disable_snd_device(adev, new_snd_devices[i]);
1533 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001534 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001535 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001536 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001537 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001538
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301539 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301540 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301541 adev->a2dp_started = false;
1542 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001543 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001544 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001545 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301546 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001547 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301548 adev->native_playback_enabled) {
1549 ALOGD("%s: %d: napb: disabling native mode in hardware",
1550 __func__, __LINE__);
1551 audio_route_reset_and_update_path(adev->audio_route,
1552 "true-native-mode");
1553 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001554 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301555 adev->asrc_mode_enabled) {
1556 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301557 disable_asrc_mode(adev);
1558 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001559 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301560 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001561 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001562 ALOGD("%s: deinit ec ref loopback", __func__);
1563 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1564 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001565
1566 audio_extn_utils_release_snd_device(snd_device);
1567 } else {
1568 if (platform_split_snd_device(adev->platform,
1569 snd_device,
1570 &num_devices,
1571 new_snd_devices) == 0) {
1572 for (i = 0; i < num_devices; i++) {
1573 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1574 }
1575 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 return 0;
1579}
1580
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001581/*
1582 legend:
1583 uc - existing usecase
1584 new_uc - new usecase
1585 d1, d11, d2 - SND_DEVICE enums
1586 a1, a2 - corresponding ANDROID device enums
1587 B1, B2 - backend strings
1588
1589case 1
1590 uc->dev d1 (a1) B1
1591 new_uc->dev d1 (a1), d2 (a2) B1, B2
1592
1593 resolution: disable and enable uc->dev on d1
1594
1595case 2
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d11 (a1) B1
1598
1599 resolution: need to switch uc since d1 and d11 are related
1600 (e.g. speaker and voice-speaker)
1601 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1602
1603case 3
1604 uc->dev d1 (a1) B1
1605 new_uc->dev d2 (a2) B2
1606
1607 resolution: no need to switch uc
1608
1609case 4
1610 uc->dev d1 (a1) B1
1611 new_uc->dev d2 (a2) B1
1612
1613 resolution: disable enable uc-dev on d2 since backends match
1614 we cannot enable two streams on two different devices if they
1615 share the same backend. e.g. if offload is on speaker device using
1616 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1617 using the same backend, offload must also be switched to voice-handset.
1618
1619case 5
1620 uc->dev d1 (a1) B1
1621 new_uc->dev d1 (a1), d2 (a2) B1
1622
1623 resolution: disable enable uc-dev on d2 since backends match
1624 we cannot enable two streams on two different devices if they
1625 share the same backend.
1626
1627case 6
1628 uc->dev d1 (a1) B1
1629 new_uc->dev d2 (a1) B2
1630
1631 resolution: no need to switch
1632
1633case 7
1634 uc->dev d1 (a1), d2 (a2) B1, B2
1635 new_uc->dev d1 (a1) B1
1636
1637 resolution: no need to switch
1638
Zhou Song4ba65882018-07-09 14:48:07 +08001639case 8
1640 uc->dev d1 (a1) B1
1641 new_uc->dev d11 (a1), d2 (a2) B1, B2
1642 resolution: compared to case 1, for this case, d1 and d11 are related
1643 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301644
1645case 9
1646 uc->dev d1 (a1), d2(a2) B1 B2
1647 new_uc->dev d1 (a1), d22 (a2) B1, B2
1648 resolution: disable enable uc-dev on d2 since backends match
1649 we cannot enable two streams on two different devices if they
1650 share the same backend. This is special case for combo use case
1651 with a2dp and sco devices which uses same backend.
1652 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001653*/
1654static snd_device_t derive_playback_snd_device(void * platform,
1655 struct audio_usecase *uc,
1656 struct audio_usecase *new_uc,
1657 snd_device_t new_snd_device)
1658{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001659 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001660
1661 snd_device_t d1 = uc->out_snd_device;
1662 snd_device_t d2 = new_snd_device;
1663
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001664 list_init(&a1);
1665 list_init(&a2);
1666
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301667 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301668 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001669 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1670 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301671 break;
1672 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001673 assign_devices(&a1, &uc->stream.out->device_list);
1674 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301675 break;
1676 }
1677
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001678 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001679 if (!compare_devices(&a1, &a2) &&
1680 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001681 snd_device_t d3[2];
1682 int num_devices = 0;
1683 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001684 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001685 &num_devices,
1686 d3);
1687 if (ret < 0) {
1688 if (ret != -ENOSYS) {
1689 ALOGW("%s failed to split snd_device %d",
1690 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001691 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001692 }
1693 goto end;
1694 }
1695
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001696 if (platform_check_backends_match(d3[0], d3[1])) {
1697 return d2; // case 5
1698 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301699 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1700 platform_check_backends_match(d1, d2))
1701 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001702 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301703 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001704 // check if d1 is related to any of d3's
1705 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001706 return d1; // case 1
1707 else
1708 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001709 }
1710 } else {
1711 if (platform_check_backends_match(d1, d2)) {
1712 return d2; // case 2, 4
1713 } else {
1714 return d1; // case 6, 3
1715 }
1716 }
1717
1718end:
1719 return d2; // return whatever was calculated before.
1720}
1721
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001722static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301723 struct audio_usecase *uc_info,
1724 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725{
1726 struct listnode *node;
1727 struct audio_usecase *usecase;
1728 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301729 snd_device_t uc_derive_snd_device;
1730 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001731 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1732 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001733 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301734 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001735 /*
1736 * This function is to make sure that all the usecases that are active on
1737 * the hardware codec backend are always routed to any one device that is
1738 * handled by the hardware codec.
1739 * For example, if low-latency and deep-buffer usecases are currently active
1740 * on speaker and out_set_parameters(headset) is received on low-latency
1741 * output, then we have to make sure deep-buffer is also switched to headset,
1742 * because of the limitation that both the devices cannot be enabled
1743 * at the same time as they share the same backend.
1744 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001745 /*
1746 * This call is to check if we need to force routing for a particular stream
1747 * If there is a backend configuration change for the device when a
1748 * new stream starts, then ADM needs to be closed and re-opened with the new
1749 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001750 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001751 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001752 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1753 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301754 /* For a2dp device reconfigure all active sessions
1755 * with new AFE encoder format based on a2dp state
1756 */
1757 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301758 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1759 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301760 audio_extn_a2dp_is_force_device_switch()) {
1761 force_routing = true;
1762 force_restart_session = true;
1763 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001764
1765 /*
1766 * Island cfg and power mode config needs to set before AFE port start.
1767 * Set force routing in case of voice device was enable before.
1768 */
1769 if (uc_info->type == VOICE_CALL &&
1770 voice_extn_is_voice_power_mode_supported() &&
1771 platform_check_and_update_island_power_status(adev->platform,
1772 uc_info,
1773 snd_device)) {
1774 force_routing = true;
1775 ALOGD("%s:becf: force routing %d for power mode supported device",
1776 __func__, force_routing);
1777 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301778 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1779
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001780 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001781 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001782 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001783 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1784 switch_device[i] = false;
1785
1786 list_for_each(node, &adev->usecase_list) {
1787 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001788
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301789 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1790 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301791 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301792 platform_get_snd_device_name(usecase->out_snd_device),
1793 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301794 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1795 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301796 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1797 usecase, uc_info, snd_device);
1798 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001799 (is_codec_backend_out_device_type(&usecase->device_list) ||
1800 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1801 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1802 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1803 is_a2dp_out_device_type(&usecase->device_list) ||
1804 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301805 ((force_restart_session) ||
1806 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301807 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1808 __func__, use_case_table[usecase->id],
1809 platform_get_snd_device_name(usecase->out_snd_device));
1810 disable_audio_route(adev, usecase);
1811 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301812 /* Enable existing usecase on derived playback device */
1813 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301814 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301815 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816 }
1817 }
1818
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301819 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1820 num_uc_to_switch);
1821
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001823 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301825 /* Make sure the previous devices to be disabled first and then enable the
1826 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 list_for_each(node, &adev->usecase_list) {
1828 usecase = node_to_item(node, struct audio_usecase, list);
1829 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001830 /* Check if output sound device to be switched can be split and if any
1831 of the split devices match with derived sound device */
1832 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1833 &num_devices, split_snd_devices) == 0) {
1834 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1835 for (i = 0; i < num_devices; i++) {
1836 /* Disable devices that do not match with derived sound device */
1837 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1838 disable_snd_device(adev, split_snd_devices[i]);
1839 }
1840 } else {
1841 disable_snd_device(adev, usecase->out_snd_device);
1842 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001843 }
1844 }
1845
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001846 list_for_each(node, &adev->usecase_list) {
1847 usecase = node_to_item(node, struct audio_usecase, list);
1848 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001849 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1850 &num_devices, split_snd_devices) == 0) {
1851 /* Enable derived sound device only if it does not match with
1852 one of the split sound devices. This is because the matching
1853 sound device was not disabled */
1854 bool should_enable = true;
1855 for (i = 0; i < num_devices; i++) {
1856 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1857 should_enable = false;
1858 break;
1859 }
1860 }
1861 if (should_enable)
1862 enable_snd_device(adev, derive_snd_device[usecase->id]);
1863 } else {
1864 enable_snd_device(adev, derive_snd_device[usecase->id]);
1865 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001866 }
1867 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 /* Re-route all the usecases on the shared backend other than the
1870 specified usecase to new snd devices */
1871 list_for_each(node, &adev->usecase_list) {
1872 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301873 /* Update the out_snd_device only before enabling the audio route */
1874 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301875 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301876 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301877 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301878 use_case_table[usecase->id],
1879 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001880 /* Update voc calibration before enabling VoIP route */
1881 if (usecase->type == VOIP_CALL)
1882 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001883 usecase->out_snd_device,
1884 platform_get_input_snd_device(
1885 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301886 &uc_info->device_list,
1887 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301888 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301889 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001890 out_set_voip_volume(&usecase->stream.out->stream,
1891 usecase->stream.out->volume_l,
1892 usecase->stream.out->volume_r);
1893 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301894 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 }
1896 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001897 }
1898}
1899
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301900static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001901 struct audio_usecase *uc_info,
1902 snd_device_t snd_device)
1903{
1904 struct listnode *node;
1905 struct audio_usecase *usecase;
1906 bool switch_device[AUDIO_USECASE_MAX];
1907 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001908 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001909 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001910
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301911 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1912 snd_device);
1913 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301914
1915 /*
1916 * Make sure out devices is checked against out codec backend device and
1917 * also in devices against in codec backend. Checking out device against in
1918 * codec backend or vice versa causes issues.
1919 */
1920 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001921 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001922
1923 /*
1924 * Island cfg and power mode config needs to set before AFE port start.
1925 * Set force routing in case of voice device was enable before.
1926 */
1927
1928 if (uc_info->type == VOICE_CALL &&
1929 voice_extn_is_voice_power_mode_supported() &&
1930 platform_check_and_update_island_power_status(adev->platform,
1931 uc_info,
1932 snd_device)) {
1933 force_routing = true;
1934 ALOGD("%s:becf: force routing %d for power mode supported device",
1935 __func__, force_routing);
1936 }
1937
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001938 /*
1939 * This function is to make sure that all the active capture usecases
1940 * are always routed to the same input sound device.
1941 * For example, if audio-record and voice-call usecases are currently
1942 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1943 * is received for voice call then we have to make sure that audio-record
1944 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1945 * because of the limitation that two devices cannot be enabled
1946 * at the same time if they share the same backend.
1947 */
1948 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1949 switch_device[i] = false;
1950
1951 list_for_each(node, &adev->usecase_list) {
1952 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301953 /*
1954 * TODO: Enhance below condition to handle BT sco/USB multi recording
1955 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301956
1957 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1958 (usecase->in_snd_device != snd_device || force_routing));
1959 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1960 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1961 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001962 ((backend_check_cond &&
1963 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001964 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001965 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001966 is_single_device_type_equal(&usecase->device_list,
1967 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001968 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001969 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001970 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301971 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001972 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001973 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001974 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001975 switch_device[usecase->id] = true;
1976 num_uc_to_switch++;
1977 }
1978 }
1979
1980 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001981 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001982
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301983 /* Make sure the previous devices to be disabled first and then enable the
1984 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001985 list_for_each(node, &adev->usecase_list) {
1986 usecase = node_to_item(node, struct audio_usecase, list);
1987 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001988 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001989 }
1990 }
1991
1992 list_for_each(node, &adev->usecase_list) {
1993 usecase = node_to_item(node, struct audio_usecase, list);
1994 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001995 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001996 }
1997 }
1998
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001999 /* Re-route all the usecases on the shared backend other than the
2000 specified usecase to new snd devices */
2001 list_for_each(node, &adev->usecase_list) {
2002 usecase = node_to_item(node, struct audio_usecase, list);
2003 /* Update the in_snd_device only before enabling the audio route */
2004 if (switch_device[usecase->id] ) {
2005 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002006 if (usecase->type != VOICE_CALL) {
2007 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302008 if (usecase->type == VOIP_CALL) {
2009 snd_device_t voip_snd_device;
2010 voip_snd_device = platform_get_output_snd_device(adev->platform,
2011 uc_info->stream.out,
2012 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002013 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302014 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002015 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302016 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302017 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002018 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002019 }
2020 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002021 }
2022}
2023
Mingming Yin3a941d42016-02-17 18:08:05 -08002024static void reset_hdmi_sink_caps(struct stream_out *out) {
2025 int i = 0;
2026
2027 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2028 out->supported_channel_masks[i] = 0;
2029 }
2030 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2031 out->supported_formats[i] = 0;
2032 }
2033 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2034 out->supported_sample_rates[i] = 0;
2035 }
2036}
2037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002039static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040{
Mingming Yin3a941d42016-02-17 18:08:05 -08002041 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002042 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2043 out->extconn.cs.controller,
2044 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045
Mingming Yin3a941d42016-02-17 18:08:05 -08002046 reset_hdmi_sink_caps(out);
2047
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002048 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002049 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002050 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002051 out->extconn.cs.stream);
2052 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002053 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002054 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002055 }
2056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002059 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002060 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002061 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2062 case 6:
2063 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2064 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2065 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2066 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2067 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2068 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 break;
2070 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002071 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002072 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 break;
2074 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002075
2076 // check channel format caps
2077 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002078 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2079 out->extconn.cs.controller,
2080 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002081 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2082 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2083 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2084 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2085 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2086 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2087 }
2088
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002089 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2090 out->extconn.cs.controller,
2091 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002092 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2093 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2094 }
2095
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002096 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2097 out->extconn.cs.controller,
2098 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002099 ALOGV(":%s HDMI supports DTS format", __func__);
2100 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2101 }
2102
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002103 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2104 out->extconn.cs.controller,
2105 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002106 ALOGV(":%s HDMI supports DTS HD format", __func__);
2107 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2108 }
2109
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002110 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2111 out->extconn.cs.controller,
2112 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002113 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2114 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2115 }
2116
Mingming Yin3a941d42016-02-17 18:08:05 -08002117
2118 // check sample rate caps
2119 i = 0;
2120 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002121 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2122 out->extconn.cs.controller,
2123 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002124 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2125 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2126 }
2127 }
2128
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002129 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130}
2131
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002132static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2133 uint32_t *supported_sample_rates __unused,
2134 uint32_t max_rates __unused)
2135{
2136 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2137 supported_sample_rates,
2138 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302139 ssize_t i = 0;
2140
2141 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002142 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2143 supported_sample_rates[i]);
2144 }
2145 return count;
2146}
2147
2148static inline int read_usb_sup_channel_masks(bool is_playback,
2149 audio_channel_mask_t *supported_channel_masks,
2150 uint32_t max_masks)
2151{
2152 int channels = audio_extn_usb_get_max_channels(is_playback);
2153 int channel_count;
2154 uint32_t num_masks = 0;
2155 if (channels > MAX_HIFI_CHANNEL_COUNT)
2156 channels = MAX_HIFI_CHANNEL_COUNT;
2157
2158 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002159 // start from 2 channels as framework currently doesn't support mono.
2160 if (channels >= FCC_2) {
2161 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2162 }
2163 for (channel_count = FCC_2;
2164 channel_count <= channels && num_masks < max_masks;
2165 ++channel_count) {
2166 supported_channel_masks[num_masks++] =
2167 audio_channel_mask_for_index_assignment_from_count(channel_count);
2168 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002169 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002170 // For capture we report all supported channel masks from 1 channel up.
2171 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002172 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2173 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002174 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2175 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2176 if (channel_count <= FCC_2) {
2177 mask = audio_channel_in_mask_from_count(channel_count);
2178 supported_channel_masks[num_masks++] = mask;
2179 }
2180 const audio_channel_mask_t index_mask =
2181 audio_channel_mask_for_index_assignment_from_count(channel_count);
2182 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2183 supported_channel_masks[num_masks++] = index_mask;
2184 }
2185 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002186 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302187
vincenttewf51c94e2019-05-07 10:28:53 +08002188 for (size_t i = 0; i < num_masks; ++i) {
2189 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2190 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302191 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002192 return num_masks;
2193}
2194
2195static inline int read_usb_sup_formats(bool is_playback __unused,
2196 audio_format_t *supported_formats,
2197 uint32_t max_formats __unused)
2198{
2199 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2200 switch (bitwidth) {
2201 case 24:
2202 // XXX : usb.c returns 24 for s24 and s24_le?
2203 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2204 break;
2205 case 32:
2206 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2207 break;
2208 case 16:
2209 default :
2210 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2211 break;
2212 }
2213 ALOGV("%s: %s supported format %d", __func__,
2214 is_playback ? "P" : "C", bitwidth);
2215 return 1;
2216}
2217
2218static inline int read_usb_sup_params_and_compare(bool is_playback,
2219 audio_format_t *format,
2220 audio_format_t *supported_formats,
2221 uint32_t max_formats,
2222 audio_channel_mask_t *mask,
2223 audio_channel_mask_t *supported_channel_masks,
2224 uint32_t max_masks,
2225 uint32_t *rate,
2226 uint32_t *supported_sample_rates,
2227 uint32_t max_rates) {
2228 int ret = 0;
2229 int num_formats;
2230 int num_masks;
2231 int num_rates;
2232 int i;
2233
2234 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2235 max_formats);
2236 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2237 max_masks);
2238
2239 num_rates = read_usb_sup_sample_rates(is_playback,
2240 supported_sample_rates, max_rates);
2241
2242#define LUT(table, len, what, dflt) \
2243 for (i=0; i<len && (table[i] != what); i++); \
2244 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2245
2246 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2247 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2248 LUT(supported_sample_rates, num_rates, *rate, 0);
2249
2250#undef LUT
2251 return ret < 0 ? -EINVAL : 0; // HACK TBD
2252}
2253
Alexy Josephb1379942016-01-29 15:49:38 -08002254audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002255 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002256{
2257 struct audio_usecase *usecase;
2258 struct listnode *node;
2259
2260 list_for_each(node, &adev->usecase_list) {
2261 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002262 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002263 ALOGV("%s: usecase id %d", __func__, usecase->id);
2264 return usecase->id;
2265 }
2266 }
2267 return USECASE_INVALID;
2268}
2269
Alexy Josephb1379942016-01-29 15:49:38 -08002270struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002271 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002272{
2273 struct audio_usecase *usecase;
2274 struct listnode *node;
2275
2276 list_for_each(node, &adev->usecase_list) {
2277 usecase = node_to_item(node, struct audio_usecase, list);
2278 if (usecase->id == uc_id)
2279 return usecase;
2280 }
2281 return NULL;
2282}
2283
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302284/*
2285 * is a true native playback active
2286 */
2287bool audio_is_true_native_stream_active(struct audio_device *adev)
2288{
2289 bool active = false;
2290 int i = 0;
2291 struct listnode *node;
2292
2293 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2294 ALOGV("%s:napb: not in true mode or non hdphones device",
2295 __func__);
2296 active = false;
2297 goto exit;
2298 }
2299
2300 list_for_each(node, &adev->usecase_list) {
2301 struct audio_usecase *uc;
2302 uc = node_to_item(node, struct audio_usecase, list);
2303 struct stream_out *curr_out =
2304 (struct stream_out*) uc->stream.out;
2305
2306 if (curr_out && PCM_PLAYBACK == uc->type) {
2307 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2308 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2309 uc->id, curr_out->sample_rate,
2310 curr_out->bit_width,
2311 platform_get_snd_device_name(uc->out_snd_device));
2312
2313 if (is_offload_usecase(uc->id) &&
2314 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2315 active = true;
2316 ALOGD("%s:napb:native stream detected", __func__);
2317 }
2318 }
2319 }
2320exit:
2321 return active;
2322}
2323
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002324uint32_t adev_get_dsp_bit_width_enforce_mode()
2325{
2326 if (adev == NULL) {
2327 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2328 return 0;
2329 }
2330 return adev->dsp_bit_width_enforce_mode;
2331}
2332
2333static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2334{
2335 char value[PROPERTY_VALUE_MAX];
2336 int trial;
2337 uint32_t dsp_bit_width_enforce_mode = 0;
2338
2339 if (!mixer) {
2340 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2341 __func__);
2342 return 0;
2343 }
2344
2345 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2346 value, NULL) > 0) {
2347 trial = atoi(value);
2348 switch (trial) {
2349 case 16:
2350 dsp_bit_width_enforce_mode = 16;
2351 break;
2352 case 24:
2353 dsp_bit_width_enforce_mode = 24;
2354 break;
2355 case 32:
2356 dsp_bit_width_enforce_mode = 32;
2357 break;
2358 default:
2359 dsp_bit_width_enforce_mode = 0;
2360 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2361 break;
2362 }
2363 }
2364
2365 return dsp_bit_width_enforce_mode;
2366}
2367
2368static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2369 uint32_t enforce_mode,
2370 bool enable)
2371{
2372 struct mixer_ctl *ctl = NULL;
2373 const char *mixer_ctl_name = "ASM Bit Width";
2374 uint32_t asm_bit_width_mode = 0;
2375
2376 if (enforce_mode == 0) {
2377 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2378 return;
2379 }
2380
2381 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2382 if (!ctl) {
2383 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2384 __func__, mixer_ctl_name);
2385 return;
2386 }
2387
2388 if (enable)
2389 asm_bit_width_mode = enforce_mode;
2390 else
2391 asm_bit_width_mode = 0;
2392
2393 ALOGV("%s DSP bit width feature status is %d width=%d",
2394 __func__, enable, asm_bit_width_mode);
2395 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2396 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2397 asm_bit_width_mode);
2398
2399 return;
2400}
2401
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302402/*
2403 * if native DSD playback active
2404 */
2405bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2406{
2407 bool active = false;
2408 struct listnode *node = NULL;
2409 struct audio_usecase *uc = NULL;
2410 struct stream_out *curr_out = NULL;
2411
2412 list_for_each(node, &adev->usecase_list) {
2413 uc = node_to_item(node, struct audio_usecase, list);
2414 curr_out = (struct stream_out*) uc->stream.out;
2415
2416 if (curr_out && PCM_PLAYBACK == uc->type &&
2417 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2418 active = true;
2419 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302420 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302421 }
2422 }
2423 return active;
2424}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302425
2426static bool force_device_switch(struct audio_usecase *usecase)
2427{
2428 bool ret = false;
2429 bool is_it_true_mode = false;
2430
Zhou Song30f2c3e2018-02-08 14:02:15 +08002431 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302432 usecase->type == TRANSCODE_LOOPBACK_RX ||
2433 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002434 return false;
2435 }
2436
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002437 if(usecase->stream.out == NULL) {
2438 ALOGE("%s: stream.out is NULL", __func__);
2439 return false;
2440 }
2441
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302442 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002443 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002444 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2445 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302446 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2447 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2448 (!is_it_true_mode && adev->native_playback_enabled)){
2449 ret = true;
2450 ALOGD("napb: time to toggle native mode");
2451 }
2452 }
2453
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302454 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302455 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2456 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002457 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302458 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302459 ALOGD("Force a2dp device switch to update new encoder config");
2460 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002461 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302462
Florian Pfister1a84f312018-07-19 14:38:18 +02002463 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302464 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2465 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002466 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302467 return ret;
2468}
2469
Aalique Grahame22e49102018-12-18 14:23:57 -08002470static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2471{
2472 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2473}
2474
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302475bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2476{
2477 bool ret=false;
2478 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002479 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2480 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302481 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2482 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002483 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302484 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002485 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2486 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302487 ret = true;
2488
2489 return ret;
2490}
2491
2492bool is_a2dp_device(snd_device_t out_snd_device)
2493{
2494 bool ret=false;
2495 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2496 ret = true;
2497
2498 return ret;
2499}
2500
2501bool is_bt_soc_on(struct audio_device *adev)
2502{
2503 struct mixer_ctl *ctl;
2504 char *mixer_ctl_name = "BT SOC status";
2505 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2506 bool bt_soc_status = true;
2507 if (!ctl) {
2508 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2509 __func__, mixer_ctl_name);
2510 /*This is to ensure we dont break targets which dont have the kernel change*/
2511 return true;
2512 }
2513 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2514 ALOGD("BT SOC status: %d",bt_soc_status);
2515 return bt_soc_status;
2516}
2517
Zhou Song331c8e52019-08-26 14:16:12 +08002518static int configure_btsco_sample_rate(snd_device_t snd_device)
2519{
2520 struct mixer_ctl *ctl = NULL;
2521 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2522 char *rate_str = NULL;
2523 bool is_rx_dev = true;
2524
2525 if (is_btsco_device(snd_device, snd_device)) {
2526 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2527 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2528 if (!ctl_sr_tx || !ctl_sr_rx) {
2529 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2530 if (!ctl_sr)
2531 return -ENOSYS;
2532 }
2533
2534 switch (snd_device) {
2535 case SND_DEVICE_OUT_BT_SCO:
2536 rate_str = "KHZ_8";
2537 break;
2538 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2539 case SND_DEVICE_IN_BT_SCO_MIC:
2540 rate_str = "KHZ_8";
2541 is_rx_dev = false;
2542 break;
2543 case SND_DEVICE_OUT_BT_SCO_WB:
2544 rate_str = "KHZ_16";
2545 break;
2546 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2547 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2548 rate_str = "KHZ_16";
2549 is_rx_dev = false;
2550 break;
2551 default:
2552 return 0;
2553 }
2554
2555 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2556 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2557 return -ENOSYS;
2558 }
2559 return 0;
2560}
2561
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302562int out_standby_l(struct audio_stream *stream);
2563
Eric Laurent637e2d42018-11-15 12:24:31 -08002564struct stream_in *adev_get_active_input(const struct audio_device *adev)
2565{
2566 struct listnode *node;
2567 struct stream_in *last_active_in = NULL;
2568
2569 /* Get last added active input.
2570 * TODO: We may use a priority mechanism to pick highest priority active source */
2571 list_for_each(node, &adev->usecase_list)
2572 {
2573 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2574 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2575 last_active_in = usecase->stream.in;
2576 }
2577
2578 return last_active_in;
2579}
2580
2581struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2582{
2583 struct listnode *node;
2584
2585 /* First check active inputs with voice communication source and then
2586 * any input if audio mode is in communication */
2587 list_for_each(node, &adev->usecase_list)
2588 {
2589 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2590 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2591 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2592 return usecase->stream.in;
2593 }
2594 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2595 return adev_get_active_input(adev);
2596
2597 return NULL;
2598}
2599
Carter Hsu2e429db2019-05-14 18:50:52 +08002600/*
2601 * Aligned with policy.h
2602 */
2603static inline int source_priority(int inputSource)
2604{
2605 switch (inputSource) {
2606 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2607 return 9;
2608 case AUDIO_SOURCE_CAMCORDER:
2609 return 8;
2610 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2611 return 7;
2612 case AUDIO_SOURCE_UNPROCESSED:
2613 return 6;
2614 case AUDIO_SOURCE_MIC:
2615 return 5;
2616 case AUDIO_SOURCE_ECHO_REFERENCE:
2617 return 4;
2618 case AUDIO_SOURCE_FM_TUNER:
2619 return 3;
2620 case AUDIO_SOURCE_VOICE_RECOGNITION:
2621 return 2;
2622 case AUDIO_SOURCE_HOTWORD:
2623 return 1;
2624 default:
2625 break;
2626 }
2627 return 0;
2628}
2629
2630static struct stream_in *get_priority_input(struct audio_device *adev)
2631{
2632 struct listnode *node;
2633 struct audio_usecase *usecase;
2634 int last_priority = 0, priority;
2635 struct stream_in *priority_in = NULL;
2636 struct stream_in *in;
2637
2638 list_for_each(node, &adev->usecase_list) {
2639 usecase = node_to_item(node, struct audio_usecase, list);
2640 if (usecase->type == PCM_CAPTURE) {
2641 in = usecase->stream.in;
2642 if (!in)
2643 continue;
2644 priority = source_priority(in->source);
2645
2646 if (priority > last_priority) {
2647 last_priority = priority;
2648 priority_in = in;
2649 }
2650 }
2651 }
2652 return priority_in;
2653}
2654
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002655int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002657 snd_device_t out_snd_device = SND_DEVICE_NONE;
2658 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002659 struct audio_usecase *usecase = NULL;
2660 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002661 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002662 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302663 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002664 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002665 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302667 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2668
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002669 usecase = get_usecase_from_list(adev, uc_id);
2670 if (usecase == NULL) {
2671 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2672 return -EINVAL;
2673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002675 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002676 (usecase->type == VOIP_CALL) ||
2677 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302678 if(usecase->stream.out == NULL) {
2679 ALOGE("%s: stream.out is NULL", __func__);
2680 return -EINVAL;
2681 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002682 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002683 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2684 uc_id);
2685 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2686 uc_id);
2687 } else {
2688 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302689 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002690 in_snd_device = platform_get_input_snd_device(adev->platform,
2691 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302692 &usecase->stream.out->device_list,
2693 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002694 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002695 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302696 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302697 if (usecase->stream.inout == NULL) {
2698 ALOGE("%s: stream.inout is NULL", __func__);
2699 return -EINVAL;
2700 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002701 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302702 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2703 stream_out.format = usecase->stream.inout->out_config.format;
2704 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302705 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002706 assign_devices(&usecase->device_list,
2707 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302708 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2709 if (usecase->stream.inout == NULL) {
2710 ALOGE("%s: stream.inout is NULL", __func__);
2711 return -EINVAL;
2712 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302713 struct listnode out_devices;
2714 list_init(&out_devices);
2715 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2716 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002717 assign_devices(&usecase->device_list,
2718 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002719 } else {
2720 /*
2721 * If the voice call is active, use the sound devices of voice call usecase
2722 * so that it would not result any device switch. All the usecases will
2723 * be switched to new device when select_devices() is called for voice call
2724 * usecase. This is to avoid switching devices for voice call when
2725 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002726 * choose voice call device only if the use case device is
2727 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002728 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002729 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002730 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002731 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002732 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2733 is_codec_backend_out_device_type(&usecase->device_list)) ||
2734 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2735 is_codec_backend_in_device_type(&usecase->device_list)) ||
2736 is_single_device_type_equal(&vc_usecase->device_list,
2737 AUDIO_DEVICE_OUT_HEARING_AID) ||
2738 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002739 AUDIO_DEVICE_IN_VOICE_CALL) ||
2740 (is_single_device_type_equal(&usecase->device_list,
2741 AUDIO_DEVICE_IN_USB_HEADSET) &&
2742 is_single_device_type_equal(&vc_usecase->device_list,
2743 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002744 in_snd_device = vc_usecase->in_snd_device;
2745 out_snd_device = vc_usecase->out_snd_device;
2746 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002747 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002748 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002749 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002750 if ((voip_usecase != NULL) &&
2751 (usecase->type == PCM_PLAYBACK) &&
2752 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002753 out_snd_device_backend_match = platform_check_backends_match(
2754 voip_usecase->out_snd_device,
2755 platform_get_output_snd_device(
2756 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302757 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002758 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2760 (is_codec_backend_out_device_type(&usecase->device_list) ||
2761 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002762 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002763 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002764 in_snd_device = voip_usecase->in_snd_device;
2765 out_snd_device = voip_usecase->out_snd_device;
2766 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002767 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002768 hfp_ucid = audio_extn_hfp_get_usecase();
2769 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002770 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002771 in_snd_device = hfp_usecase->in_snd_device;
2772 out_snd_device = hfp_usecase->out_snd_device;
2773 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002774 }
2775 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302776 if (usecase->stream.out == NULL) {
2777 ALOGE("%s: stream.out is NULL", __func__);
2778 return -EINVAL;
2779 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002780 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002781 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002782 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002783 struct stream_out *voip_out = adev->primary_output;
2784 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002785 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002786 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2787 else
2788 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302789 usecase->stream.out,
2790 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002791 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002792
Eric Laurent637e2d42018-11-15 12:24:31 -08002793 if (voip_usecase)
2794 voip_out = voip_usecase->stream.out;
2795
2796 if (usecase->stream.out == voip_out && voip_in != NULL)
2797 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002798 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002799 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302800 if (usecase->stream.in == NULL) {
2801 ALOGE("%s: stream.in is NULL", __func__);
2802 return -EINVAL;
2803 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002804 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002805 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002806 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002808 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002809 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002810
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002811 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002812 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002813 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2814 USECASE_AUDIO_PLAYBACK_VOIP);
2815
Carter Hsu2e429db2019-05-14 18:50:52 +08002816 usecase->stream.in->enable_ec_port = false;
2817
Zhou Song62ea0282020-03-22 19:53:01 +08002818 bool is_ha_usecase = adev->ha_proxy_enable ?
2819 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2820 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2821 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002822 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002823 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002824 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002825 } else if (adev->primary_output &&
2826 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002827 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002828 } else {
2829 /* forcing speaker o/p device to get matching i/p pair
2830 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002831 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002832 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002833 priority_in = voip_in;
2834 } else {
2835 /* get the input with the highest priority source*/
2836 priority_in = get_priority_input(adev);
2837
2838 if (!priority_in)
2839 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002840 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002841
Eric Laurent637e2d42018-11-15 12:24:31 -08002842 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002843 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302844 &out_devices,
2845 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002847 }
2848 }
2849
2850 if (out_snd_device == usecase->out_snd_device &&
2851 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302852
2853 if (!force_device_switch(usecase))
2854 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 }
2856
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002857 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002858 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002859 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002860 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2861 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302862 }
2863
Aalique Grahame22e49102018-12-18 14:23:57 -08002864 if (out_snd_device != SND_DEVICE_NONE &&
2865 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2866 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2867 __func__,
2868 use_case_table[uc_id],
2869 adev->last_logged_snd_device[uc_id][0],
2870 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2871 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2872 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2873 -1,
2874 out_snd_device,
2875 platform_get_snd_device_name(out_snd_device),
2876 platform_get_snd_device_acdb_id(out_snd_device));
2877 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2878 }
2879 if (in_snd_device != SND_DEVICE_NONE &&
2880 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2881 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2882 __func__,
2883 use_case_table[uc_id],
2884 adev->last_logged_snd_device[uc_id][1],
2885 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2886 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2887 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2888 -1,
2889 in_snd_device,
2890 platform_get_snd_device_name(in_snd_device),
2891 platform_get_snd_device_acdb_id(in_snd_device));
2892 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2893 }
2894
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 /*
2897 * Limitation: While in call, to do a device switch we need to disable
2898 * and enable both RX and TX devices though one of them is same as current
2899 * device.
2900 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002901 if ((usecase->type == VOICE_CALL) &&
2902 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2903 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002904 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002905 }
2906
2907 if (((usecase->type == VOICE_CALL) ||
2908 (usecase->type == VOIP_CALL)) &&
2909 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2910 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302911 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002912 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002913 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002914
2915 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302916 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002917 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002918 }
2919
Aalique Grahame22e49102018-12-18 14:23:57 -08002920 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2921 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002922 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302923 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002924 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2925 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2926 else
2927 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302928 }
2929
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002930 /* Disable current sound devices */
2931 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002932 disable_audio_route(adev, usecase);
2933 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 }
2935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002937 disable_audio_route(adev, usecase);
2938 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 }
2940
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002941 /* Applicable only on the targets that has external modem.
2942 * New device information should be sent to modem before enabling
2943 * the devices to reduce in-call device switch time.
2944 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002945 if ((usecase->type == VOICE_CALL) &&
2946 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2947 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002948 status = platform_switch_voice_call_enable_device_config(adev->platform,
2949 out_snd_device,
2950 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002951 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002953 /* Enable new sound devices */
2954 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002955 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302956 if (platform_check_codec_asrc_support(adev->platform))
2957 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002958 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 }
2960
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002961 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302962 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002963 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002964 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002965
Avinash Vaish71a8b972014-07-24 15:36:33 +05302966 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002967 status = platform_switch_voice_call_device_post(adev->platform,
2968 out_snd_device,
2969 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302970 enable_audio_route_for_voice_usecases(adev, usecase);
2971 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002972
sangwoo170731f2013-06-08 15:36:36 +09002973 usecase->in_snd_device = in_snd_device;
2974 usecase->out_snd_device = out_snd_device;
2975
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302976 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2977 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302978 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002979 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002980 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002981 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2982 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2983 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2984 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2985 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2986 /*
2987 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2988 * configured device sample rate, if not update the COPP rate to be equal to the
2989 * device sample rate, else open COPP at stream sample rate
2990 */
2991 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2992 usecase->stream.out->sample_rate,
2993 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302994 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302995 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2996 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302997 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002998 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2999 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3000 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3001 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003002 }
3003 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003004
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003005 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003006
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003007 /* If input stream is already running then effect needs to be
3008 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003009 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003010 check_and_enable_effect(adev);
3011
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003012 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003013 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303014 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003015 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3016
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003017 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303018 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003019 voice_extn_compress_voip_is_started(adev))
3020 voice_set_sidetone(adev, out_snd_device, true);
3021 }
3022
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003023 /* Applicable only on the targets that has external modem.
3024 * Enable device command should be sent to modem only after
3025 * enabling voice call mixer controls
3026 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003027 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003028 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3029 out_snd_device,
3030 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303031
3032 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003033 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303034 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003035 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303036 if (is_bt_soc_on(adev) == false){
3037 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003038 if (in->pcm != NULL)
3039 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303040 }
3041 }
3042 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3043 && usecase->stream.out->started) {
3044 if (is_bt_soc_on(adev) == false) {
3045 ALOGD("BT SCO/A2DP disconnected while in connection");
3046 out_standby_l(&usecase->stream.out->stream.common);
3047 }
3048 }
3049 } else if ((usecase->stream.out != NULL) &&
3050 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303051 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3052 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003053 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303054 usecase->stream.out->started) {
3055 if (is_bt_soc_on(adev) == false) {
3056 ALOGD("BT SCO/A2dp disconnected while in connection");
3057 out_standby_l(&usecase->stream.out->stream.common);
3058 }
3059 }
3060 }
3061
Yung Ti Su70cb8242018-06-22 17:38:47 +08003062 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003063 struct stream_out *voip_out = voip_usecase->stream.out;
3064 audio_extn_utils_send_app_type_gain(adev,
3065 voip_out->app_type_cfg.app_type,
3066 &voip_out->app_type_cfg.gain[0]);
3067 }
3068
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303069 ALOGD("%s: done",__func__);
3070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 return status;
3072}
3073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074static int stop_input_stream(struct stream_in *in)
3075{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303076 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303078
3079 if (in == NULL) {
3080 ALOGE("%s: stream_in ptr is NULL", __func__);
3081 return -EINVAL;
3082 }
3083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003085 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086
Eric Laurent994a6932013-07-17 11:51:42 -07003087 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003088 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 uc_info = get_usecase_from_list(adev, in->usecase);
3090 if (uc_info == NULL) {
3091 ALOGE("%s: Could not find the usecase (%d) in the list",
3092 __func__, in->usecase);
3093 return -EINVAL;
3094 }
3095
Carter Hsu2e429db2019-05-14 18:50:52 +08003096 priority_in = get_priority_input(adev);
3097
Derek Chenea197282019-01-07 17:35:01 -08003098 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3099 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003100
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003101 /* Close in-call recording streams */
3102 voice_check_and_stop_incall_rec_usecase(adev, in);
3103
Eric Laurent150dbfe2013-02-27 14:31:02 -08003104 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003105 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003106
3107 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003108 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003110 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303111 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3112
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003113 list_remove(&uc_info->list);
3114 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115
Carter Hsu2e429db2019-05-14 18:50:52 +08003116 if (priority_in == in) {
3117 priority_in = get_priority_input(adev);
3118 if (priority_in)
3119 select_devices(adev, priority_in->usecase);
3120 }
3121
Vatsal Buchac09ae062018-11-14 13:25:08 +05303122 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003123 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 return ret;
3125}
3126
3127int start_input_stream(struct stream_in *in)
3128{
3129 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003130 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303132
3133 if (in == NULL) {
3134 ALOGE("%s: stream_in ptr is NULL", __func__);
3135 return -EINVAL;
3136 }
3137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003139 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003140 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
Mingming Yin2664a5b2015-09-03 10:53:11 -07003142 if (get_usecase_from_list(adev, usecase) == NULL)
3143 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303144 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3145 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003146
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303147 if (CARD_STATUS_OFFLINE == in->card_status||
3148 CARD_STATUS_OFFLINE == adev->card_status) {
3149 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303150 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 goto error_config;
3152 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303153
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003154 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303155 if (!adev->bt_sco_on) {
3156 ALOGE("%s: SCO profile is not ready, return error", __func__);
3157 ret = -EIO;
3158 goto error_config;
3159 }
3160 }
3161
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003162 /* Check if source matches incall recording usecase criteria */
3163 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3164 if (ret)
3165 goto error_config;
3166 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003167 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3168
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303169 if (audio_extn_cin_attached_usecase(in))
3170 audio_extn_cin_acquire_usecase(in);
3171
Mingming Yin2664a5b2015-09-03 10:53:11 -07003172 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3173 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3174 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003175 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003176 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003177
Eric Laurentb23d5282013-05-14 15:27:20 -07003178 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 if (in->pcm_device_id < 0) {
3180 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3181 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003182 ret = -EINVAL;
3183 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003187
3188 if (!uc_info) {
3189 ret = -ENOMEM;
3190 goto error_config;
3191 }
3192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 uc_info->id = in->usecase;
3194 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003195 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003196 list_init(&uc_info->device_list);
3197 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003198 uc_info->in_snd_device = SND_DEVICE_NONE;
3199 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003201 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003202 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303203 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3204 adev->perf_lock_opts,
3205 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003206 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207
Derek Chenea197282019-01-07 17:35:01 -08003208 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3209 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003210
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303211 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3212
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303213 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303214 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303215 if (ret)
3216 goto error_open;
3217 else
3218 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003219 }
3220
Haynes Mathew George16081042017-05-31 17:16:49 -07003221 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003222 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003223 ALOGE("%s: pcm stream not ready", __func__);
3224 goto error_open;
3225 }
3226 ret = pcm_start(in->pcm);
3227 if (ret < 0) {
3228 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3229 goto error_open;
3230 }
3231 } else {
3232 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3233 unsigned int pcm_open_retry_count = 0;
3234
Zhou Song62ea0282020-03-22 19:53:01 +08003235 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3236 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003237 flags |= PCM_MMAP | PCM_NOIRQ;
3238 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3239 } else if (in->realtime) {
3240 flags |= PCM_MMAP | PCM_NOIRQ;
3241 }
3242
Garmond Leunge2433c32017-09-28 21:51:22 -07003243 if (audio_extn_ffv_get_stream() == in) {
3244 ALOGD("%s: ffv stream, update pcm config", __func__);
3245 audio_extn_ffv_update_pcm_config(&config);
3246 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003247 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3248 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3249
3250 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003251 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003252 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003253 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003254 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303255 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303256 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3257 adev->card_status = CARD_STATUS_OFFLINE;
3258 in->card_status = CARD_STATUS_OFFLINE;
3259 ret = -EIO;
3260 goto error_open;
3261 }
3262
Haynes Mathew George16081042017-05-31 17:16:49 -07003263 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3264 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3265 if (in->pcm != NULL) {
3266 pcm_close(in->pcm);
3267 in->pcm = NULL;
3268 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003269 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003270 ret = -EIO;
3271 goto error_open;
3272 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003273 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3275 continue;
3276 }
3277 break;
3278 }
3279
3280 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003281 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003282 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003283 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003284 if (ret < 0) {
3285 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3286 pcm_close(in->pcm);
3287 in->pcm = NULL;
3288 goto error_open;
3289 }
3290 register_in_stream(in);
3291 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003292 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003293 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003294 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003295 if (ret < 0) {
3296 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003297 pcm_close(in->pcm);
3298 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003299 goto error_open;
3300 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003301 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003302 }
3303
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003304 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003305 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3306 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003307
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003308 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303309 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3310
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303311done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003312 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303313 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003314 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303315 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003316 return ret;
3317
3318error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003319 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303320 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003322
Eric Laurentc8400632013-02-14 19:04:54 -08003323error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303324 /*
3325 * sleep 50ms to allow sufficient time for kernel
3326 * drivers to recover incases like SSR.
3327 */
3328 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003329 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303330 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003331 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332}
3333
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003334void lock_input_stream(struct stream_in *in)
3335{
3336 pthread_mutex_lock(&in->pre_lock);
3337 pthread_mutex_lock(&in->lock);
3338 pthread_mutex_unlock(&in->pre_lock);
3339}
3340
3341void lock_output_stream(struct stream_out *out)
3342{
3343 pthread_mutex_lock(&out->pre_lock);
3344 pthread_mutex_lock(&out->lock);
3345 pthread_mutex_unlock(&out->pre_lock);
3346}
3347
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348/* must be called with out->lock locked */
3349static int send_offload_cmd_l(struct stream_out* out, int command)
3350{
3351 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3352
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003353 if (!cmd) {
3354 ALOGE("failed to allocate mem for command 0x%x", command);
3355 return -ENOMEM;
3356 }
3357
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 ALOGVV("%s %d", __func__, command);
3359
3360 cmd->cmd = command;
3361 list_add_tail(&out->offload_cmd_list, &cmd->node);
3362 pthread_cond_signal(&out->offload_cond);
3363 return 0;
3364}
3365
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003366/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367static void stop_compressed_output_l(struct stream_out *out)
3368{
3369 out->offload_state = OFFLOAD_STATE_IDLE;
3370 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003371 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 if (out->compr != NULL) {
3373 compress_stop(out->compr);
3374 while (out->offload_thread_blocked) {
3375 pthread_cond_wait(&out->cond, &out->lock);
3376 }
3377 }
3378}
3379
Varun Balaraje49253e2017-07-06 19:48:56 +05303380bool is_interactive_usecase(audio_usecase_t uc_id)
3381{
3382 unsigned int i;
3383 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3384 if (uc_id == interactive_usecases[i])
3385 return true;
3386 }
3387 return false;
3388}
3389
3390static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3391{
3392 audio_usecase_t ret_uc = USECASE_INVALID;
3393 unsigned int intract_uc_index;
3394 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3395
3396 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3397 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3398 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3399 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3400 ret_uc = interactive_usecases[intract_uc_index];
3401 break;
3402 }
3403 }
3404
3405 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3406 return ret_uc;
3407}
3408
3409static void free_interactive_usecase(struct audio_device *adev,
3410 audio_usecase_t uc_id)
3411{
3412 unsigned int interact_uc_index;
3413 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3414
3415 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3416 if (interactive_usecases[interact_uc_index] == uc_id) {
3417 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3418 break;
3419 }
3420 }
3421 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3422}
3423
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003424bool is_offload_usecase(audio_usecase_t uc_id)
3425{
3426 unsigned int i;
3427 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3428 if (uc_id == offload_usecases[i])
3429 return true;
3430 }
3431 return false;
3432}
3433
Dhananjay Kumarac341582017-02-23 23:42:25 +05303434static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003435{
vivek mehta446c3962015-09-14 10:57:35 -07003436 audio_usecase_t ret_uc = USECASE_INVALID;
3437 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003438 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003439 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303440 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003441 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3442 else
3443 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003444
vivek mehta446c3962015-09-14 10:57:35 -07003445 pthread_mutex_lock(&adev->lock);
3446 if (get_usecase_from_list(adev, ret_uc) != NULL)
3447 ret_uc = USECASE_INVALID;
3448 pthread_mutex_unlock(&adev->lock);
3449
3450 return ret_uc;
3451 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003452
3453 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003454 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3455 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3456 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3457 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003458 break;
3459 }
3460 }
vivek mehta446c3962015-09-14 10:57:35 -07003461
3462 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3463 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464}
3465
3466static void free_offload_usecase(struct audio_device *adev,
3467 audio_usecase_t uc_id)
3468{
vivek mehta446c3962015-09-14 10:57:35 -07003469 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003470 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003471
3472 if (!adev->multi_offload_enable)
3473 return;
3474
3475 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3476 if (offload_usecases[offload_uc_index] == uc_id) {
3477 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003478 break;
3479 }
3480 }
3481 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3482}
3483
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484static void *offload_thread_loop(void *context)
3485{
3486 struct stream_out *out = (struct stream_out *) context;
3487 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003488 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003491 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3493
3494 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003495 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003496 out->offload_state = OFFLOAD_STATE_IDLE;
3497 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 for (;;) {
3499 struct offload_cmd *cmd = NULL;
3500 stream_callback_event_t event;
3501 bool send_callback = false;
3502
3503 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3504 __func__, list_empty(&out->offload_cmd_list),
3505 out->offload_state);
3506 if (list_empty(&out->offload_cmd_list)) {
3507 ALOGV("%s SLEEPING", __func__);
3508 pthread_cond_wait(&out->offload_cond, &out->lock);
3509 ALOGV("%s RUNNING", __func__);
3510 continue;
3511 }
3512
3513 item = list_head(&out->offload_cmd_list);
3514 cmd = node_to_item(item, struct offload_cmd, node);
3515 list_remove(item);
3516
3517 ALOGVV("%s STATE %d CMD %d out->compr %p",
3518 __func__, out->offload_state, cmd->cmd, out->compr);
3519
3520 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3521 free(cmd);
3522 break;
3523 }
3524
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003525 // allow OFFLOAD_CMD_ERROR reporting during standby
3526 // this is needed to handle failures during compress_open
3527 // Note however that on a pause timeout, the stream is closed
3528 // and no offload usecase will be active. Therefore this
3529 // special case is needed for compress_open failures alone
3530 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3531 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003532 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003533 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003534 pthread_cond_signal(&out->cond);
3535 continue;
3536 }
3537 out->offload_thread_blocked = true;
3538 pthread_mutex_unlock(&out->lock);
3539 send_callback = false;
3540 switch(cmd->cmd) {
3541 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003542 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003544 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003545 send_callback = true;
3546 event = STREAM_CBK_EVENT_WRITE_READY;
3547 break;
3548 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003549 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303550 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003551 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303552 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003553 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303554 if (ret < 0)
3555 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303556 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303557 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003558 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003559 else
3560 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003561 if (-ENETRESET != ret && !(-EINTR == ret &&
3562 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303563 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303564 pthread_mutex_lock(&out->lock);
3565 out->send_new_metadata = 1;
3566 out->send_next_track_params = true;
3567 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303568 event = STREAM_CBK_EVENT_DRAIN_READY;
3569 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3570 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303571 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003572 break;
3573 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003574 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003575 ret = compress_drain(out->compr);
3576 ALOGD("copl(%p):out of compress_drain", out);
3577 // EINTR check avoids drain interruption due to SSR
3578 if (-ENETRESET != ret && !(-EINTR == ret &&
3579 CARD_STATUS_OFFLINE == out->card_status)) {
3580 send_callback = true;
3581 event = STREAM_CBK_EVENT_DRAIN_READY;
3582 } else
3583 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303585 case OFFLOAD_CMD_ERROR:
3586 ALOGD("copl(%p): sending error callback to AF", out);
3587 send_callback = true;
3588 event = STREAM_CBK_EVENT_ERROR;
3589 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003590 default:
3591 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3592 break;
3593 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003594 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003595 out->offload_thread_blocked = false;
3596 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003597 if (send_callback && out->client_callback) {
3598 ALOGVV("%s: sending client_callback event %d", __func__, event);
3599 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003600 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003601 free(cmd);
3602 }
3603
3604 pthread_cond_signal(&out->cond);
3605 while (!list_empty(&out->offload_cmd_list)) {
3606 item = list_head(&out->offload_cmd_list);
3607 list_remove(item);
3608 free(node_to_item(item, struct offload_cmd, node));
3609 }
3610 pthread_mutex_unlock(&out->lock);
3611
3612 return NULL;
3613}
3614
3615static int create_offload_callback_thread(struct stream_out *out)
3616{
3617 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3618 list_init(&out->offload_cmd_list);
3619 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3620 offload_thread_loop, out);
3621 return 0;
3622}
3623
3624static int destroy_offload_callback_thread(struct stream_out *out)
3625{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003626 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003627 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003628 stop_compressed_output_l(out);
3629 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3630
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003631 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003632 pthread_mutex_unlock(&out->lock);
3633 pthread_join(out->offload_thread, (void **) NULL);
3634 pthread_cond_destroy(&out->offload_cond);
3635
3636 return 0;
3637}
3638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639static int stop_output_stream(struct stream_out *out)
3640{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303641 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 struct audio_usecase *uc_info;
3643 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003644 bool has_voip_usecase =
3645 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646
Eric Laurent994a6932013-07-17 11:51:42 -07003647 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003648 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 uc_info = get_usecase_from_list(adev, out->usecase);
3650 if (uc_info == NULL) {
3651 ALOGE("%s: Could not find the usecase (%d) in the list",
3652 __func__, out->usecase);
3653 return -EINVAL;
3654 }
3655
Derek Chenea197282019-01-07 17:35:01 -08003656 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3657 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003658
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003659 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303660 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003661 if (adev->visualizer_stop_output != NULL)
3662 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003663
3664 audio_extn_dts_remove_state_notifier_node(out->usecase);
3665
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003666 if (adev->offload_effects_stop_output != NULL)
3667 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003668 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3669 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3670 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003671 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003672
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003673 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3674 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003675 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003676 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003677
Eric Laurent150dbfe2013-02-27 14:31:02 -08003678 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003679 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003680
3681 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003682 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683
Aalique Grahame22e49102018-12-18 14:23:57 -08003684 audio_extn_extspk_update(adev->extspk);
3685
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003686 if (is_offload_usecase(out->usecase)) {
3687 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3688 adev->dsp_bit_width_enforce_mode,
3689 false);
3690 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003691 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003692 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3693 false);
3694
3695 if (ret != 0)
3696 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3697 /* default service interval was successfully updated,
3698 reopen USB backend with new service interval */
3699 ret = 0;
3700 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003701
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003702 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303703 out->started = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003704 pthread_mutex_lock(&out->latch_lock);
3705 out->muted = false;
3706 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003707 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303708 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003709 ALOGV("Disable passthrough , reset mixer to pcm");
3710 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003711#ifdef AUDIO_GKI_ENABLED
3712 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3713 out->compr_config.codec->reserved[0] = 0;
3714#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003715 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003716#endif
Mingming Yin21854652016-04-13 11:54:02 -07003717 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003718 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3719 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003720
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303721 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003722 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303723 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303724
Manish Dewangan21a850a2017-08-14 12:03:55 +05303725 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003726 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3727 if (ret < 0)
3728 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3729 }
3730
juyuchen2d415992018-11-16 14:15:16 +08003731 /* 1) media + voip output routing to handset must route media back to
3732 speaker when voip stops.
3733 2) trigger voip input to reroute when voip output changes to
3734 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003735 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003736 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003737 struct listnode *node;
3738 struct audio_usecase *usecase;
3739 list_for_each(node, &adev->usecase_list) {
3740 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003741 if ((usecase->type == PCM_CAPTURE &&
3742 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3743 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003744 continue;
3745
3746 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3747 __func__, usecase->id, use_case_table[usecase->id],
3748 out->usecase, use_case_table[out->usecase]);
3749 select_devices(adev, usecase->id);
3750 }
3751 }
3752
Garmond Leung5fd0b552018-04-17 11:56:12 -07003753 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003754 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 return ret;
3756}
3757
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003758struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3759 unsigned int flags, unsigned int pcm_open_retry_count,
3760 struct pcm_config *config)
3761{
3762 struct pcm* pcm = NULL;
3763
3764 while (1) {
3765 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3766 if (pcm == NULL || !pcm_is_ready(pcm)) {
3767 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3768 if (pcm != NULL) {
3769 pcm_close(pcm);
3770 pcm = NULL;
3771 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003772 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003773 return NULL;
3774
Weiyin Jiang72197252019-10-09 11:49:32 +08003775 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003776 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3777 continue;
3778 }
3779 break;
3780 }
3781
3782 if (pcm_is_ready(pcm)) {
3783 int ret = pcm_prepare(pcm);
3784 if (ret < 0) {
3785 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3786 pcm_close(pcm);
3787 pcm = NULL;
3788 }
3789 }
3790
3791 return pcm;
3792}
3793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794int start_output_stream(struct stream_out *out)
3795{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 struct audio_usecase *uc_info;
3798 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003799 char mixer_ctl_name[128];
3800 struct mixer_ctl *ctl = NULL;
3801 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303802 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003803 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Haynes Mathew George380745d2017-10-04 15:27:45 -07003805 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003806 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3807 ret = -EINVAL;
3808 goto error_config;
3809 }
3810
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003811 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303812 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003813 get_device_types(&out->device_list), is_haptic_usecase);
3814
3815 bool is_speaker_active = compare_device_type(&out->device_list,
3816 AUDIO_DEVICE_OUT_SPEAKER);
3817 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3818 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303819
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303820 if (CARD_STATUS_OFFLINE == out->card_status ||
3821 CARD_STATUS_OFFLINE == adev->card_status) {
3822 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303823 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003824 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303825 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303826
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003827 //Update incall music usecase to reflect correct voice session
3828 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3829 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3830 if (ret != 0) {
3831 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3832 __func__, ret);
3833 goto error_config;
3834 }
3835 }
3836
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003837 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003838 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003839 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303840 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303841 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303842 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3843 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3844 ret = -EAGAIN;
3845 goto error_config;
3846 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303847 }
3848 }
3849 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003850 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303851 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003852 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303853 //combo usecase just by pass a2dp
3854 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003855 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303856 } else {
3857 ALOGE("%s: SCO profile is not ready, return error", __func__);
3858 ret = -EAGAIN;
3859 goto error_config;
3860 }
3861 }
3862 }
3863
Eric Laurentb23d5282013-05-14 15:27:20 -07003864 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 if (out->pcm_device_id < 0) {
3866 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3867 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003868 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003869 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 }
3871
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003872 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003873 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3874 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003875 if (adev->haptic_pcm_device_id < 0) {
3876 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3877 __func__, adev->haptic_pcm_device_id, out->usecase);
3878 ret = -EINVAL;
3879 goto error_config;
3880 }
3881 }
3882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003884
3885 if (!uc_info) {
3886 ret = -ENOMEM;
3887 goto error_config;
3888 }
3889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 uc_info->id = out->usecase;
3891 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003892 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003893 list_init(&uc_info->device_list);
3894 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003895 uc_info->in_snd_device = SND_DEVICE_NONE;
3896 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003897
3898 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003899 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003900 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3901 /* USB backend is not reopened immediately.
3902 This is eventually done as part of select_devices */
3903 }
3904
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003905 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906
Wei Wangf7ca6c92017-11-21 14:51:20 -08003907 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303908 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3909 adev->perf_lock_opts,
3910 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303911
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003912 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303913 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303914 if (audio_extn_passthru_is_enabled() &&
3915 audio_extn_passthru_is_passthrough_stream(out)) {
3916 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303917 }
3918 }
3919
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003920 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003921 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303922 if (!a2dp_combo) {
3923 check_a2dp_restore_l(adev, out, false);
3924 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003925 struct listnode dev;
3926 list_init(&dev);
3927 assign_devices(&dev, &out->device_list);
3928 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3929 reassign_device_list(&out->device_list,
3930 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003931 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003932 reassign_device_list(&out->device_list,
3933 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303934 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003935 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303936 }
3937 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303938 select_devices(adev, out->usecase);
3939 if (is_a2dp_out_device_type(&out->device_list) &&
3940 !adev->a2dp_started) {
3941 if (is_speaker_active || is_speaker_safe_active) {
3942 struct listnode dev;
3943 list_init(&dev);
3944 assign_devices(&dev, &out->device_list);
3945 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3946 reassign_device_list(&out->device_list,
3947 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3948 else
3949 reassign_device_list(&out->device_list,
3950 AUDIO_DEVICE_OUT_SPEAKER, "");
3951 select_devices(adev, out->usecase);
3952 assign_devices(&out->device_list, &dev);
3953 } else {
3954 ret = -EINVAL;
3955 goto error_open;
3956 }
3957 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303958 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003959
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003960 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3961 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003962 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003963 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003964
Derek Chenea197282019-01-07 17:35:01 -08003965 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3966 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003967
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003968 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3969 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003970
3971 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003972 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003973 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3974 ALOGE("%s: pcm stream not ready", __func__);
3975 goto error_open;
3976 }
3977 ret = pcm_start(out->pcm);
3978 if (ret < 0) {
3979 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3980 goto error_open;
3981 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003982 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003983 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003984 unsigned int flags = PCM_OUT;
3985 unsigned int pcm_open_retry_count = 0;
3986 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3987 flags |= PCM_MMAP | PCM_NOIRQ;
3988 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003989 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003990 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003991 } else
3992 flags |= PCM_MONOTONIC;
3993
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003994 if ((adev->vr_audio_mode_enabled) &&
3995 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3996 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3997 "PCM_Dev %d Topology", out->pcm_device_id);
3998 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3999 if (!ctl) {
4000 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4001 __func__, mixer_ctl_name);
4002 } else {
4003 //if success use ULLPP
4004 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4005 __func__, mixer_ctl_name, out->pcm_device_id);
4006 //There is a still a possibility that some sessions
4007 // that request for FAST|RAW when 3D audio is active
4008 //can go through ULLPP. Ideally we expects apps to
4009 //listen to audio focus and stop concurrent playback
4010 //Also, we will look for mode flag (voice_in_communication)
4011 //before enabling the realtime flag.
4012 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4013 }
4014 }
4015
Surendar Karka91fa3682018-07-02 18:12:12 +05304016 if (out->realtime)
4017 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4018 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4019
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004020 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4021 flags, pcm_open_retry_count,
4022 &(out->config));
4023 if (out->pcm == NULL) {
4024 ret = -EIO;
4025 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004026 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004027
4028 if (is_haptic_usecase) {
4029 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4030 adev->haptic_pcm_device_id,
4031 flags, pcm_open_retry_count,
4032 &(adev->haptics_config));
4033 // failure to open haptics pcm shouldnt stop audio,
4034 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004035
4036 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4037 ALOGD("%s: enable haptic audio synchronization", __func__);
4038 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4039 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004040 }
4041
Surendar Karka91fa3682018-07-02 18:12:12 +05304042 if (!out->realtime)
4043 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304044 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004045
Zhou Song2b8f28f2017-09-11 10:51:38 +08004046 // apply volume for voip playback after path is set up
4047 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4048 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304049 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4050 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304051 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4052 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004053 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4054 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304055 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004056 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004057 /*
4058 * set custom channel map if:
4059 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4060 * 2. custom channel map has been set by client
4061 * else default channel map of FC/FR/FL can always be set to DSP
4062 */
4063 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4064 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4065 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004066 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4067 adev->dsp_bit_width_enforce_mode,
4068 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004070 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004071 out->compr = compress_open(adev->snd_card,
4072 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004073 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004074 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304075 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304076 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4077 adev->card_status = CARD_STATUS_OFFLINE;
4078 out->card_status = CARD_STATUS_OFFLINE;
4079 ret = -EIO;
4080 goto error_open;
4081 }
4082
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004083 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004084 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004085 compress_close(out->compr);
4086 out->compr = NULL;
4087 ret = -EIO;
4088 goto error_open;
4089 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304090 /* compress_open sends params of the track, so reset the flag here */
4091 out->is_compr_metadata_avail = false;
4092
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004093 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004094 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004095
Fred Oh3f43e742015-03-04 18:42:34 -08004096 /* Since small bufs uses blocking writes, a write will be blocked
4097 for the default max poll time (20s) in the event of an SSR.
4098 Reduce the poll time to observe and deal with SSR faster.
4099 */
Ashish Jain5106d362016-05-11 19:23:33 +05304100 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004101 compress_set_max_poll_wait(out->compr, 1000);
4102 }
4103
Manish Dewangan69426c82017-01-30 17:35:36 +05304104 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304105 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304106
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004107 audio_extn_dts_create_state_notifier_node(out->usecase);
4108 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4109 popcount(out->channel_mask),
4110 out->playback_started);
4111
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004112#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304113 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004114 audio_extn_dolby_send_ddp_endp_params(adev);
4115#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304116 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4117 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004118 if (adev->visualizer_start_output != NULL)
4119 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4120 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304121 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004122 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004123 }
Derek Chenf13dd492018-11-13 14:53:51 -08004124
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004125 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004126 /* Update cached volume from media to offload/direct stream */
4127 struct listnode *node = NULL;
4128 list_for_each(node, &adev->active_outputs_list) {
4129 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4130 streams_output_ctxt_t,
4131 list);
4132 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4133 out->volume_l = out_ctxt->output->volume_l;
4134 out->volume_r = out_ctxt->output->volume_r;
4135 }
4136 }
4137 out_set_compr_volume(&out->stream,
4138 out->volume_l, out->volume_r);
4139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004141
4142 if (ret == 0) {
4143 register_out_stream(out);
4144 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004145 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4146 ALOGE("%s: pcm stream not ready", __func__);
4147 goto error_open;
4148 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004149 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004150 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004151 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004152 if (ret < 0)
4153 goto error_open;
4154 }
4155 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004156 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304157 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004158 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004159
vivek mehtad15d2bf2019-05-17 13:35:10 -07004160 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4161 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4162 audio_low_latency_hint_start();
4163 }
4164
Manish Dewangan21a850a2017-08-14 12:03:55 +05304165 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004166 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004167 if (ret < 0)
4168 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4169 }
4170
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004171 // consider a scenario where on pause lower layers are tear down.
4172 // so on resume, swap mixer control need to be sent only when
4173 // backend is active, hence rather than sending from enable device
4174 // sending it from start of streamtream
4175
4176 platform_set_swap_channels(adev, true);
4177
Haynes Mathew George380745d2017-10-04 15:27:45 -07004178 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304179 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004180 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004181error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004182 if (adev->haptic_pcm) {
4183 pcm_close(adev->haptic_pcm);
4184 adev->haptic_pcm = NULL;
4185 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004186 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304187 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004189error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304190 /*
4191 * sleep 50ms to allow sufficient time for kernel
4192 * drivers to recover incases like SSR.
4193 */
4194 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004195error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004196 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304197 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004198 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199}
4200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201static int check_input_parameters(uint32_t sample_rate,
4202 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004203 int channel_count,
4204 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004206 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304208 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4209 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4210 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004211 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004212 !audio_extn_compr_cap_format_supported(format) &&
4213 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004214 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004215
Aalique Grahame22e49102018-12-18 14:23:57 -08004216 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4217 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4218 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4219 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4220 return -EINVAL;
4221 }
4222
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004223 switch (channel_count) {
4224 case 1:
4225 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304226 case 3:
4227 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004228 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004229 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304230 case 10:
4231 case 12:
4232 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004233 break;
4234 default:
4235 ret = -EINVAL;
4236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237
4238 switch (sample_rate) {
4239 case 8000:
4240 case 11025:
4241 case 12000:
4242 case 16000:
4243 case 22050:
4244 case 24000:
4245 case 32000:
4246 case 44100:
4247 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004248 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304249 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004250 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304251 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 break;
4253 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004254 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 }
4256
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004257 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258}
4259
Naresh Tanniru04f71882018-06-26 17:46:22 +05304260
4261/** Add a value in a list if not already present.
4262 * @return true if value was successfully inserted or already present,
4263 * false if the list is full and does not contain the value.
4264 */
4265static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4266 for (size_t i = 0; i < list_length; i++) {
4267 if (list[i] == value) return true; // value is already present
4268 if (list[i] == 0) { // no values in this slot
4269 list[i] = value;
4270 return true; // value inserted
4271 }
4272 }
4273 return false; // could not insert value
4274}
4275
4276/** Add channel_mask in supported_channel_masks if not already present.
4277 * @return true if channel_mask was successfully inserted or already present,
4278 * false if supported_channel_masks is full and does not contain channel_mask.
4279 */
4280static void register_channel_mask(audio_channel_mask_t channel_mask,
4281 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4282 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4283 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4284}
4285
4286/** Add format in supported_formats if not already present.
4287 * @return true if format was successfully inserted or already present,
4288 * false if supported_formats is full and does not contain format.
4289 */
4290static void register_format(audio_format_t format,
4291 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4292 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4293 "%s: stream can not declare supporting its format %x", __func__, format);
4294}
4295/** Add sample_rate in supported_sample_rates if not already present.
4296 * @return true if sample_rate was successfully inserted or already present,
4297 * false if supported_sample_rates is full and does not contain sample_rate.
4298 */
4299static void register_sample_rate(uint32_t sample_rate,
4300 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4301 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4302 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4303}
4304
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004305static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4306{
4307 uint32_t high = num1, low = num2, temp = 0;
4308
4309 if (!num1 || !num2)
4310 return 0;
4311
4312 if (num1 < num2) {
4313 high = num2;
4314 low = num1;
4315 }
4316
4317 while (low != 0) {
4318 temp = low;
4319 low = high % low;
4320 high = temp;
4321 }
4322 return (num1 * num2)/high;
4323}
4324
4325static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4326{
4327 uint32_t remainder = 0;
4328
4329 if (!multiplier)
4330 return num;
4331
4332 remainder = num % multiplier;
4333 if (remainder)
4334 num += (multiplier - remainder);
4335
4336 return num;
4337}
4338
Aalique Grahame22e49102018-12-18 14:23:57 -08004339static size_t get_stream_buffer_size(size_t duration_ms,
4340 uint32_t sample_rate,
4341 audio_format_t format,
4342 int channel_count,
4343 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344{
4345 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004346 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347
Aalique Grahame22e49102018-12-18 14:23:57 -08004348 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004349 if (is_low_latency)
4350 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304351
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004352 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004353 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354
Ralf Herzbd08d632018-09-28 15:50:49 +02004355 /* make sure the size is multiple of 32 bytes and additionally multiple of
4356 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004357 * At 48 kHz mono 16-bit PCM:
4358 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4359 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004360 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004361 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004362 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004363
4364 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365}
4366
Aalique Grahame22e49102018-12-18 14:23:57 -08004367static size_t get_input_buffer_size(uint32_t sample_rate,
4368 audio_format_t format,
4369 int channel_count,
4370 bool is_low_latency)
4371{
4372 /* Don't know if USB HIFI in this context so use true to be conservative */
4373 if (check_input_parameters(sample_rate, format, channel_count,
4374 true /*is_usb_hifi */) != 0)
4375 return 0;
4376
4377 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4378 sample_rate,
4379 format,
4380 channel_count,
4381 is_low_latency);
4382}
4383
Derek Chenf6318be2017-06-12 17:16:24 -04004384size_t get_output_period_size(uint32_t sample_rate,
4385 audio_format_t format,
4386 int channel_count,
4387 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304388{
4389 size_t size = 0;
4390 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4391
4392 if ((duration == 0) || (sample_rate == 0) ||
4393 (bytes_per_sample == 0) || (channel_count == 0)) {
4394 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4395 bytes_per_sample, channel_count);
4396 return -EINVAL;
4397 }
4398
4399 size = (sample_rate *
4400 duration *
4401 bytes_per_sample *
4402 channel_count) / 1000;
4403 /*
4404 * To have same PCM samples for all channels, the buffer size requires to
4405 * be multiple of (number of channels * bytes per sample)
4406 * For writes to succeed, the buffer must be written at address which is multiple of 32
4407 */
4408 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4409
4410 return (size/(channel_count * bytes_per_sample));
4411}
4412
Zhou Song48453a02018-01-10 17:50:59 +08004413static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304414{
4415 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004416 uint64_t written_frames = 0;
4417 uint64_t kernel_frames = 0;
4418 uint64_t dsp_frames = 0;
4419 uint64_t signed_frames = 0;
4420 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304421
4422 /* This adjustment accounts for buffering after app processor.
4423 * It is based on estimated DSP latency per use case, rather than exact.
4424 */
George Gao9ba8a142020-07-23 14:30:03 -07004425 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004426 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304427
Zhou Song48453a02018-01-10 17:50:59 +08004428 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004429 written_frames = out->written /
4430 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4431
Ashish Jain5106d362016-05-11 19:23:33 +05304432 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4433 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4434 * hence only estimate.
4435 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004436 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4437 kernel_frames = kernel_buffer_size /
4438 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304439
Weiyin Jiang4813da12020-05-28 00:37:28 +08004440 if (written_frames >= (kernel_frames + dsp_frames))
4441 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304442
Zhou Song48453a02018-01-10 17:50:59 +08004443 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304444 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004445 if (timestamp != NULL )
4446 *timestamp = out->writeAt;
4447 } else if (timestamp != NULL) {
4448 clock_gettime(CLOCK_MONOTONIC, timestamp);
4449 }
4450 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304451
Weiyin Jiang4813da12020-05-28 00:37:28 +08004452 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4453 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304454
4455 return actual_frames_rendered;
4456}
4457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4459{
4460 struct stream_out *out = (struct stream_out *)stream;
4461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004462 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463}
4464
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004465static int out_set_sample_rate(struct audio_stream *stream __unused,
4466 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467{
4468 return -ENOSYS;
4469}
4470
4471static size_t out_get_buffer_size(const struct audio_stream *stream)
4472{
4473 struct stream_out *out = (struct stream_out *)stream;
4474
Varun Balaraje49253e2017-07-06 19:48:56 +05304475 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304476 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304477 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304478 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4479 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4480 else
4481 return out->compr_config.fragment_size;
4482 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004483 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304484 else if (is_offload_usecase(out->usecase) &&
4485 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304486 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004487
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004488 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004489 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490}
4491
4492static uint32_t out_get_channels(const struct audio_stream *stream)
4493{
4494 struct stream_out *out = (struct stream_out *)stream;
4495
4496 return out->channel_mask;
4497}
4498
4499static audio_format_t out_get_format(const struct audio_stream *stream)
4500{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004501 struct stream_out *out = (struct stream_out *)stream;
4502
4503 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504}
4505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004506static int out_set_format(struct audio_stream *stream __unused,
4507 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508{
4509 return -ENOSYS;
4510}
4511
4512static int out_standby(struct audio_stream *stream)
4513{
4514 struct stream_out *out = (struct stream_out *)stream;
4515 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004516 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004517
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304518 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4519 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004521 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004523 if (adev->adm_deregister_stream)
4524 adev->adm_deregister_stream(adev->adm_data, out->handle);
4525
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004526 if (is_offload_usecase(out->usecase)) {
4527 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004528 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004529 pthread_mutex_unlock(&out->latch_lock);
4530 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004531
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004532 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004534 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4535 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304536 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004537 pthread_mutex_unlock(&adev->lock);
4538 pthread_mutex_unlock(&out->lock);
4539 ALOGD("VOIP output entered standby");
4540 return 0;
4541 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004542 if (out->pcm) {
4543 pcm_close(out->pcm);
4544 out->pcm = NULL;
4545 }
Meng Wanga09da002020-04-20 12:56:04 +08004546 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4547 if (adev->haptic_pcm) {
4548 pcm_close(adev->haptic_pcm);
4549 adev->haptic_pcm = NULL;
4550 }
4551
4552 if (adev->haptic_buffer != NULL) {
4553 free(adev->haptic_buffer);
4554 adev->haptic_buffer = NULL;
4555 adev->haptic_buffer_size = 0;
4556 }
4557 adev->haptic_pcm_device_id = 0;
4558 }
4559
Haynes Mathew George16081042017-05-31 17:16:49 -07004560 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4561 do_stop = out->playback_started;
4562 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004563
4564 if (out->mmap_shared_memory_fd >= 0) {
4565 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4566 __func__, out->mmap_shared_memory_fd);
4567 close(out->mmap_shared_memory_fd);
4568 out->mmap_shared_memory_fd = -1;
4569 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004570 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004571 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004572 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304573 out->send_next_track_params = false;
4574 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004575 out->gapless_mdata.encoder_delay = 0;
4576 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004577 if (out->compr != NULL) {
4578 compress_close(out->compr);
4579 out->compr = NULL;
4580 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004581 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004582 if (do_stop) {
4583 stop_output_stream(out);
4584 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304585 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004586 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004587 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 }
4589 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304590 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 return 0;
4592}
4593
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304594static int out_on_error(struct audio_stream *stream)
4595{
4596 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004597 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304598
4599 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004600 // always send CMD_ERROR for offload streams, this
4601 // is needed e.g. when SSR happens within compress_open
4602 // since the stream is active, offload_callback_thread is also active.
4603 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004604 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004605 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004606 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004607 }
4608 pthread_mutex_unlock(&out->lock);
4609
4610 status = out_standby(&out->stream.common);
4611
4612 lock_output_stream(out);
4613 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004614 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304615 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304616
4617 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4618 ALOGD("Setting previous card status if offline");
4619 out->prev_card_status_offline = true;
4620 }
4621
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304622 pthread_mutex_unlock(&out->lock);
4623
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004624 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304625}
4626
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304627/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004628 * standby implementation without locks, assumes that the callee already
4629 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304630 */
4631int out_standby_l(struct audio_stream *stream)
4632{
4633 struct stream_out *out = (struct stream_out *)stream;
4634 struct audio_device *adev = out->dev;
4635
4636 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4637 stream, out->usecase, use_case_table[out->usecase]);
4638
4639 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004640 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304641 if (adev->adm_deregister_stream)
4642 adev->adm_deregister_stream(adev->adm_data, out->handle);
4643
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004644 if (is_offload_usecase(out->usecase)) {
4645 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304646 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004647 pthread_mutex_unlock(&out->latch_lock);
4648 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304649
4650 out->standby = true;
4651 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4652 voice_extn_compress_voip_close_output_stream(stream);
4653 out->started = 0;
4654 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004655 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304656 return 0;
4657 } else if (!is_offload_usecase(out->usecase)) {
4658 if (out->pcm) {
4659 pcm_close(out->pcm);
4660 out->pcm = NULL;
4661 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004662 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4663 if (adev->haptic_pcm) {
4664 pcm_close(adev->haptic_pcm);
4665 adev->haptic_pcm = NULL;
4666 }
4667
4668 if (adev->haptic_buffer != NULL) {
4669 free(adev->haptic_buffer);
4670 adev->haptic_buffer = NULL;
4671 adev->haptic_buffer_size = 0;
4672 }
4673 adev->haptic_pcm_device_id = 0;
4674 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304675 } else {
4676 ALOGD("copl(%p):standby", out);
4677 out->send_next_track_params = false;
4678 out->is_compr_metadata_avail = false;
4679 out->gapless_mdata.encoder_delay = 0;
4680 out->gapless_mdata.encoder_padding = 0;
4681 if (out->compr != NULL) {
4682 compress_close(out->compr);
4683 out->compr = NULL;
4684 }
4685 }
4686 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004687 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304688 }
4689 ALOGD("%s: exit", __func__);
4690 return 0;
4691}
4692
Aalique Grahame22e49102018-12-18 14:23:57 -08004693static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694{
Aalique Grahame22e49102018-12-18 14:23:57 -08004695 struct stream_out *out = (struct stream_out *)stream;
4696
4697 // We try to get the lock for consistency,
4698 // but it isn't necessary for these variables.
4699 // If we're not in standby, we may be blocked on a write.
4700 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4701 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4702 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4703
Andy Hunga1f48fa2019-07-01 18:14:53 -07004704 char buffer[256]; // for statistics formatting
4705 if (!is_offload_usecase(out->usecase)) {
4706 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4707 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4708 }
4709
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004710 if (out->start_latency_ms.n > 0) {
4711 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4712 dprintf(fd, " Start latency ms: %s\n", buffer);
4713 }
4714
Aalique Grahame22e49102018-12-18 14:23:57 -08004715 if (locked) {
4716 pthread_mutex_unlock(&out->lock);
4717 }
4718
4719 // dump error info
4720 (void)error_log_dump(
4721 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 return 0;
4724}
4725
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004726static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4727{
4728 int ret = 0;
4729 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004730
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004731 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004732 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004733 return -EINVAL;
4734 }
4735
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304736 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004737
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004738 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4739 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304740 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004741 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004742 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4743 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304744 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004745 }
4746
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004747 ALOGV("%s new encoder delay %u and padding %u", __func__,
4748 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4749
4750 return 0;
4751}
4752
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004753static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4754{
4755 return out == adev->primary_output || out == adev->voice_tx_output;
4756}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004757
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304758// note: this call is safe only if the stream_cb is
4759// removed first in close_output_stream (as is done now).
4760static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4761{
4762 if (!stream || !parms)
4763 return;
4764
4765 struct stream_out *out = (struct stream_out *)stream;
4766 struct audio_device *adev = out->dev;
4767
4768 card_status_t status;
4769 int card;
4770 if (parse_snd_card_status(parms, &card, &status) < 0)
4771 return;
4772
4773 pthread_mutex_lock(&adev->lock);
4774 bool valid_cb = (card == adev->snd_card);
4775 pthread_mutex_unlock(&adev->lock);
4776
4777 if (!valid_cb)
4778 return;
4779
4780 lock_output_stream(out);
4781 if (out->card_status != status)
4782 out->card_status = status;
4783 pthread_mutex_unlock(&out->lock);
4784
4785 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4786 use_case_table[out->usecase],
4787 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4788
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304789 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304790 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304791 if (voice_is_call_state_active(adev) &&
4792 out == adev->primary_output) {
4793 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4794 pthread_mutex_lock(&adev->lock);
4795 voice_stop_call(adev);
4796 adev->mode = AUDIO_MODE_NORMAL;
4797 pthread_mutex_unlock(&adev->lock);
4798 }
4799 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304800 return;
4801}
4802
Kevin Rocardfce19002017-08-07 19:21:36 -07004803static int get_alive_usb_card(struct str_parms* parms) {
4804 int card;
4805 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4806 !audio_extn_usb_alive(card)) {
4807 return card;
4808 }
4809 return -ENODEV;
4810}
4811
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004812int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004813 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004814{
4815 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004817 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004818 bool bypass_a2dp = false;
4819 bool reconfig = false;
4820 unsigned long service_interval = 0;
4821
4822 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004823 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4824
4825 list_init(&new_devices);
4826 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004827
4828 lock_output_stream(out);
4829 pthread_mutex_lock(&adev->lock);
4830
4831 /*
4832 * When HDMI cable is unplugged the music playback is paused and
4833 * the policy manager sends routing=0. But the audioflinger continues
4834 * to write data until standby time (3sec). As the HDMI core is
4835 * turned off, the write gets blocked.
4836 * Avoid this by routing audio to speaker until standby.
4837 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004838 if (is_single_device_type_equal(&out->device_list,
4839 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004840 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004841 !audio_extn_passthru_is_passthrough_stream(out) &&
4842 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004843 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004844 }
4845 /*
4846 * When A2DP is disconnected the
4847 * music playback is paused and the policy manager sends routing=0
4848 * But the audioflinger continues to write data until standby time
4849 * (3sec). As BT is turned off, the write gets blocked.
4850 * Avoid this by routing audio to speaker until standby.
4851 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004852 if (is_a2dp_out_device_type(&out->device_list) &&
4853 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854 !audio_extn_a2dp_source_is_ready() &&
4855 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004856 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857 }
4858 /*
4859 * When USB headset is disconnected the music platback paused
4860 * and the policy manager send routing=0. But if the USB is connected
4861 * back before the standby time, AFE is not closed and opened
4862 * when USB is connected back. So routing to speker will guarantee
4863 * AFE reconfiguration and AFE will be opend once USB is connected again
4864 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004865 if (is_usb_out_device_type(&out->device_list) &&
4866 list_empty(&new_devices) &&
4867 !audio_extn_usb_connected(NULL)) {
4868 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4869 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870 /* To avoid a2dp to sco overlapping / BT device improper state
4871 * check with BT lib about a2dp streaming support before routing
4872 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004873 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004874 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004875 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4876 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004877 //combo usecase just by pass a2dp
4878 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4879 bypass_a2dp = true;
4880 } else {
4881 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4882 /* update device to a2dp and don't route as BT returned error
4883 * However it is still possible a2dp routing called because
4884 * of current active device disconnection (like wired headset)
4885 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004886 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 pthread_mutex_unlock(&adev->lock);
4888 pthread_mutex_unlock(&out->lock);
4889 goto error;
4890 }
4891 }
4892 }
4893
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004894 // Workaround: If routing to an non existing usb device, fail gracefully
4895 // The routing request will otherwise block during 10 second
4896 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004897 if (is_usb_out_device_type(&new_devices)) {
4898 struct str_parms *parms =
4899 str_parms_create_str(get_usb_device_address(&new_devices));
4900 if (!parms)
4901 goto error;
4902 if ((card = get_alive_usb_card(parms)) >= 0) {
4903 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4904 pthread_mutex_unlock(&adev->lock);
4905 pthread_mutex_unlock(&out->lock);
4906 str_parms_destroy(parms);
4907 ret = -ENOSYS;
4908 goto error;
4909 }
4910 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004911 }
4912
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004913 // Workaround: If routing to an non existing hdmi device, fail gracefully
4914 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4915 (platform_get_edid_info_v2(adev->platform,
4916 out->extconn.cs.controller,
4917 out->extconn.cs.stream) != 0)) {
4918 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4919 pthread_mutex_unlock(&adev->lock);
4920 pthread_mutex_unlock(&out->lock);
4921 ret = -ENOSYS;
4922 goto error;
4923 }
4924
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004925 /*
4926 * select_devices() call below switches all the usecases on the same
4927 * backend to the new device. Refer to check_usecases_codec_backend() in
4928 * the select_devices(). But how do we undo this?
4929 *
4930 * For example, music playback is active on headset (deep-buffer usecase)
4931 * and if we go to ringtones and select a ringtone, low-latency usecase
4932 * will be started on headset+speaker. As we can't enable headset+speaker
4933 * and headset devices at the same time, select_devices() switches the music
4934 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4935 * So when the ringtone playback is completed, how do we undo the same?
4936 *
4937 * We are relying on the out_set_parameters() call on deep-buffer output,
4938 * once the ringtone playback is ended.
4939 * NOTE: We should not check if the current devices are same as new devices.
4940 * Because select_devices() must be called to switch back the music
4941 * playback to headset.
4942 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004943 if (!list_empty(&new_devices)) {
4944 bool same_dev = compare_devices(&out->device_list, &new_devices);
4945 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004946
4947 if (output_drives_call(adev, out)) {
4948 if (!voice_is_call_state_active(adev)) {
4949 if (adev->mode == AUDIO_MODE_IN_CALL) {
4950 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004951 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004952 service_interval =
4953 audio_extn_usb_find_service_interval(true, true /*playback*/);
4954 audio_extn_usb_set_service_interval(true /*playback*/,
4955 service_interval,
4956 &reconfig);
4957 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4958 }
4959 ret = voice_start_call(adev);
4960 }
4961 } else {
4962 adev->current_call_output = out;
4963 voice_update_devices_for_all_voice_usecases(adev);
4964 }
4965 }
4966
4967 if (!out->standby) {
4968 if (!same_dev) {
4969 ALOGV("update routing change");
4970 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4971 adev->perf_lock_opts,
4972 adev->perf_lock_opts_size);
4973 if (adev->adm_on_routing_change)
4974 adev->adm_on_routing_change(adev->adm_data,
4975 out->handle);
4976 }
4977 if (!bypass_a2dp) {
4978 select_devices(adev, out->usecase);
4979 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004980 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4981 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004982 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004983 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004984 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004985 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 }
4987
4988 if (!same_dev) {
4989 // on device switch force swap, lower functions will make sure
4990 // to check if swap is allowed or not.
4991 platform_set_swap_channels(adev, true);
4992 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4993 }
4994 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004995 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004996 pthread_mutex_lock(&out->latch_lock);
4997 if (out->a2dp_compress_mute) {
4998 out->a2dp_compress_mute = false;
4999 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5000 }
5001 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005002 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5003 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5004 }
5005 }
5006 }
5007
5008 pthread_mutex_unlock(&adev->lock);
5009 pthread_mutex_unlock(&out->lock);
5010
5011 /*handles device and call state changes*/
5012 audio_extn_extspk_update(adev->extspk);
5013
5014error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005015 ALOGV("%s: exit: code(%d)", __func__, ret);
5016 return ret;
5017}
5018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5020{
5021 struct stream_out *out = (struct stream_out *)stream;
5022 struct audio_device *adev = out->dev;
5023 struct str_parms *parms;
5024 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005025 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005026 int ext_controller = -1;
5027 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028
sangwoobc677242013-08-08 16:53:43 +09005029 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005030 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305032 if (!parms)
5033 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005034
5035 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5036 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005037 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005038 out->extconn.cs.controller = ext_controller;
5039 out->extconn.cs.stream = ext_stream;
5040 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5041 use_case_table[out->usecase], out->extconn.cs.controller,
5042 out->extconn.cs.stream);
5043 }
5044
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005045 if (out == adev->primary_output) {
5046 pthread_mutex_lock(&adev->lock);
5047 audio_extn_set_parameters(adev, parms);
5048 pthread_mutex_unlock(&adev->lock);
5049 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005050 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005051 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005052 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005053
5054 audio_extn_dts_create_state_notifier_node(out->usecase);
5055 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5056 popcount(out->channel_mask),
5057 out->playback_started);
5058
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005059 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005060 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005061
Surendar Karkaf51b5842018-04-26 11:28:38 +05305062 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5063 sizeof(value));
5064 if (err >= 0) {
5065 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5066 audio_extn_send_dual_mono_mixing_coefficients(out);
5067 }
5068
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305069 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5070 if (err >= 0) {
5071 strlcpy(out->profile, value, sizeof(out->profile));
5072 ALOGV("updating stream profile with value '%s'", out->profile);
5073 lock_output_stream(out);
5074 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5075 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005076 &out->device_list, out->flags,
5077 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305078 out->sample_rate, out->bit_width,
5079 out->channel_mask, out->profile,
5080 &out->app_type_cfg);
5081 pthread_mutex_unlock(&out->lock);
5082 }
5083
Alexy Joseph98988832017-01-13 14:56:59 -08005084 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005085 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5086 // and vendor.audio.hal.output.suspend.supported is set to true
5087 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005088 //check suspend parameter only for low latency and if the property
5089 //is enabled
5090 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5091 ALOGI("%s: got suspend_playback %s", __func__, value);
5092 lock_output_stream(out);
5093 if (!strncmp(value, "false", 5)) {
5094 //suspend_playback=false is supposed to set QOS value back to 75%
5095 //the mixer control sent with value Enable will achieve that
5096 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5097 } else if (!strncmp (value, "true", 4)) {
5098 //suspend_playback=true is supposed to remove QOS value
5099 //resetting the mixer control will set the default value
5100 //for the mixer control which is Disable and this removes the QOS vote
5101 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5102 } else {
5103 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5104 " got %s", __func__, value);
5105 ret = -1;
5106 }
5107
5108 if (ret != 0) {
5109 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5110 __func__, out->pm_qos_mixer_path, ret);
5111 }
5112
5113 pthread_mutex_unlock(&out->lock);
5114 }
5115 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005116
Alexy Joseph98988832017-01-13 14:56:59 -08005117 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305119error:
Eric Laurent994a6932013-07-17 11:51:42 -07005120 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 return ret;
5122}
5123
Paul McLeana50b7332018-12-17 08:24:21 -07005124static int in_set_microphone_direction(const struct audio_stream_in *stream,
5125 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005126 struct stream_in *in = (struct stream_in *)stream;
5127
5128 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5129
5130 in->direction = dir;
5131
5132 if (in->standby)
5133 return 0;
5134
5135 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005136}
5137
5138static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005139 struct stream_in *in = (struct stream_in *)stream;
5140
5141 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5142
5143 if (zoom > 1.0 || zoom < -1.0)
5144 return -EINVAL;
5145
5146 in->zoom = zoom;
5147
5148 if (in->standby)
5149 return 0;
5150
5151 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005152}
5153
5154
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005155static bool stream_get_parameter_channels(struct str_parms *query,
5156 struct str_parms *reply,
5157 audio_channel_mask_t *supported_channel_masks) {
5158 int ret = -1;
5159 char value[512];
5160 bool first = true;
5161 size_t i, j;
5162
5163 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5164 ret = 0;
5165 value[0] = '\0';
5166 i = 0;
5167 while (supported_channel_masks[i] != 0) {
5168 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5169 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5170 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305171 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005172
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305173 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005174 first = false;
5175 break;
5176 }
5177 }
5178 i++;
5179 }
5180 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5181 }
5182 return ret == 0;
5183}
5184
5185static bool stream_get_parameter_formats(struct str_parms *query,
5186 struct str_parms *reply,
5187 audio_format_t *supported_formats) {
5188 int ret = -1;
5189 char value[256];
5190 size_t i, j;
5191 bool first = true;
5192
5193 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5194 ret = 0;
5195 value[0] = '\0';
5196 i = 0;
5197 while (supported_formats[i] != 0) {
5198 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5199 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5200 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305201 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005202 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305203 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005204 first = false;
5205 break;
5206 }
5207 }
5208 i++;
5209 }
5210 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5211 }
5212 return ret == 0;
5213}
5214
5215static bool stream_get_parameter_rates(struct str_parms *query,
5216 struct str_parms *reply,
5217 uint32_t *supported_sample_rates) {
5218
5219 int i;
5220 char value[256];
5221 int ret = -1;
5222 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5223 ret = 0;
5224 value[0] = '\0';
5225 i=0;
5226 int cursor = 0;
5227 while (supported_sample_rates[i]) {
5228 int avail = sizeof(value) - cursor;
5229 ret = snprintf(value + cursor, avail, "%s%d",
5230 cursor > 0 ? "|" : "",
5231 supported_sample_rates[i]);
5232 if (ret < 0 || ret >= avail) {
5233 // if cursor is at the last element of the array
5234 // overwrite with \0 is duplicate work as
5235 // snprintf already put a \0 in place.
5236 // else
5237 // we had space to write the '|' at value[cursor]
5238 // (which will be overwritten) or no space to fill
5239 // the first element (=> cursor == 0)
5240 value[cursor] = '\0';
5241 break;
5242 }
5243 cursor += ret;
5244 ++i;
5245 }
5246 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5247 value);
5248 }
5249 return ret >= 0;
5250}
5251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5253{
5254 struct stream_out *out = (struct stream_out *)stream;
5255 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005256 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005257 char value[256];
5258 struct str_parms *reply = str_parms_create();
5259 size_t i, j;
5260 int ret;
5261 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005262
5263 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005264 if (reply) {
5265 str_parms_destroy(reply);
5266 }
5267 if (query) {
5268 str_parms_destroy(query);
5269 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005270 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5271 return NULL;
5272 }
5273
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005274 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005275 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5276 if (ret >= 0) {
5277 value[0] = '\0';
5278 i = 0;
5279 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005280 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5281 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005282 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005283 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005284 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005285 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005286 first = false;
5287 break;
5288 }
5289 }
5290 i++;
5291 }
5292 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5293 str = str_parms_to_str(reply);
5294 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005295 voice_extn_out_get_parameters(out, query, reply);
5296 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005298
Alexy Joseph62142aa2015-11-16 15:10:34 -08005299
5300 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5301 if (ret >= 0) {
5302 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305303 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5304 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005305 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305306 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005307 } else {
5308 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305309 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005310 }
5311 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005312 if (str)
5313 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005314 str = str_parms_to_str(reply);
5315 }
5316
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005317 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5318 if (ret >= 0) {
5319 value[0] = '\0';
5320 i = 0;
5321 first = true;
5322 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005323 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5324 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005325 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005326 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005327 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005328 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005329 first = false;
5330 break;
5331 }
5332 }
5333 i++;
5334 }
5335 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005336 if (str)
5337 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005338 str = str_parms_to_str(reply);
5339 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005340
5341 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5342 if (ret >= 0) {
5343 value[0] = '\0';
5344 i = 0;
5345 first = true;
5346 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005347 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5348 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005349 if (!first) {
5350 strlcat(value, "|", sizeof(value));
5351 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005352 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005353 first = false;
5354 break;
5355 }
5356 }
5357 i++;
5358 }
5359 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5360 if (str)
5361 free(str);
5362 str = str_parms_to_str(reply);
5363 }
5364
Alexy Joseph98988832017-01-13 14:56:59 -08005365 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5366 //only low latency track supports suspend_resume
5367 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005368 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005369 if (str)
5370 free(str);
5371 str = str_parms_to_str(reply);
5372 }
5373
5374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375 str_parms_destroy(query);
5376 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005377 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378 return str;
5379}
5380
5381static uint32_t out_get_latency(const struct audio_stream_out *stream)
5382{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005383 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005385 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005386
Alexy Josephaa54c872014-12-03 02:46:47 -08005387 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305388 lock_output_stream(out);
5389 latency = audio_extn_utils_compress_get_dsp_latency(out);
5390 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005391 } else if ((out->realtime) ||
5392 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005393 // since the buffer won't be filled up faster than realtime,
5394 // return a smaller number
5395 if (out->config.rate)
5396 period_ms = (out->af_period_multiplier * out->config.period_size *
5397 1000) / (out->config.rate);
5398 else
5399 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005400 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005401 } else {
5402 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005403 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005404 }
5405
Zhou Songd2537a02020-06-11 22:04:46 +08005406 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005407 latency += audio_extn_a2dp_get_encoder_latency();
5408
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305409 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005410 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005411}
5412
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305413static float AmpToDb(float amplification)
5414{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305415 float db = DSD_VOLUME_MIN_DB;
5416 if (amplification > 0) {
5417 db = 20 * log10(amplification);
5418 if(db < DSD_VOLUME_MIN_DB)
5419 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305420 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305421 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305422}
5423
Arun Mirpuri5d170872019-03-26 13:21:31 -07005424static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5425 float right)
5426{
5427 struct stream_out *out = (struct stream_out *)stream;
5428 long volume = 0;
5429 char mixer_ctl_name[128] = "";
5430 struct audio_device *adev = out->dev;
5431 struct mixer_ctl *ctl = NULL;
5432 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5433 PCM_PLAYBACK);
5434
5435 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5436 "Playback %d Volume", pcm_device_id);
5437 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5438 if (!ctl) {
5439 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5440 __func__, mixer_ctl_name);
5441 return -EINVAL;
5442 }
5443 if (left != right)
5444 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5445 __func__, left, right);
5446 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5447 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5448 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5449 __func__, mixer_ctl_name, volume);
5450 return -EINVAL;
5451 }
5452 return 0;
5453}
5454
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305455static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5456 float right)
5457{
5458 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305459 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305460 char mixer_ctl_name[128];
5461 struct audio_device *adev = out->dev;
5462 struct mixer_ctl *ctl;
5463 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5464 PCM_PLAYBACK);
5465
5466 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5467 "Compress Playback %d Volume", pcm_device_id);
5468 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5469 if (!ctl) {
5470 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5471 __func__, mixer_ctl_name);
5472 return -EINVAL;
5473 }
5474 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5475 __func__, mixer_ctl_name, left, right);
5476 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5477 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5478 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5479
5480 return 0;
5481}
5482
Zhou Song2b8f28f2017-09-11 10:51:38 +08005483static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5484 float right)
5485{
5486 struct stream_out *out = (struct stream_out *)stream;
5487 char mixer_ctl_name[] = "App Type Gain";
5488 struct audio_device *adev = out->dev;
5489 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305490 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005491
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005492 if (!is_valid_volume(left, right)) {
5493 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5494 __func__, left, right);
5495 return -EINVAL;
5496 }
5497
Zhou Song2b8f28f2017-09-11 10:51:38 +08005498 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5499 if (!ctl) {
5500 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5501 __func__, mixer_ctl_name);
5502 return -EINVAL;
5503 }
5504
5505 set_values[0] = 0; //0: Rx Session 1:Tx Session
5506 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305507 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5508 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005509
5510 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5511 return 0;
5512}
5513
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305514static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5515 float right)
5516{
5517 struct stream_out *out = (struct stream_out *)stream;
5518 /* Volume control for pcm playback */
5519 if (left != right) {
5520 return -EINVAL;
5521 } else {
5522 char mixer_ctl_name[128];
5523 struct audio_device *adev = out->dev;
5524 struct mixer_ctl *ctl;
5525 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5526 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5527 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5528 if (!ctl) {
5529 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5530 return -EINVAL;
5531 }
5532
5533 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5534 int ret = mixer_ctl_set_value(ctl, 0, volume);
5535 if (ret < 0) {
5536 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5537 return -EINVAL;
5538 }
5539
5540 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5541
5542 return 0;
5543 }
5544}
5545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005546static int out_set_volume(struct audio_stream_out *stream, float left,
5547 float right)
5548{
Eric Laurenta9024de2013-04-04 09:19:12 -07005549 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005550 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305551 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005552
Arun Mirpuri5d170872019-03-26 13:21:31 -07005553 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005554 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5555 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005556 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005557 out->muted = (left == 0.0f);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005558 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005559 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005560 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305561 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005562 /*
5563 * Set mute or umute on HDMI passthrough stream.
5564 * Only take left channel into account.
5565 * Mute is 0 and unmute 1
5566 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305567 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305568 } else if (out->format == AUDIO_FORMAT_DSD){
5569 char mixer_ctl_name[128] = "DSD Volume";
5570 struct audio_device *adev = out->dev;
5571 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5572
5573 if (!ctl) {
5574 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5575 __func__, mixer_ctl_name);
5576 return -EINVAL;
5577 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305578 volume[0] = (long)(AmpToDb(left));
5579 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305580 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5581 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005582 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005583 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005584 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5585 struct listnode *node = NULL;
5586 list_for_each(node, &adev->active_outputs_list) {
5587 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5588 streams_output_ctxt_t,
5589 list);
5590 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5591 out->volume_l = out_ctxt->output->volume_l;
5592 out->volume_r = out_ctxt->output->volume_r;
5593 }
5594 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005595 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005596 if (!out->a2dp_compress_mute) {
5597 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5598 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005599 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005600 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005601 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005602 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005603 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305604 if (!out->a2dp_compress_mute)
5605 ret = out_set_compr_volume(stream, left, right);
5606 out->volume_l = left;
5607 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005608 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305609 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005611 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005612 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5613 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5614 if (!out->standby) {
5615 audio_extn_utils_send_app_type_gain(out->dev,
5616 out->app_type_cfg.app_type,
5617 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005618 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005619 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005620 out->volume_l = left;
5621 out->volume_r = right;
5622 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005623 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5624 ALOGV("%s: MMAP set volume called", __func__);
5625 if (!out->standby)
5626 ret = out_set_mmap_volume(stream, left, right);
5627 out->volume_l = left;
5628 out->volume_r = right;
5629 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305630 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305631 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5632 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305633 /* Volume control for pcm playback */
5634 if (!out->standby)
5635 ret = out_set_pcm_volume(stream, left, right);
5636 else
5637 out->apply_volume = true;
5638
5639 out->volume_l = left;
5640 out->volume_r = right;
5641 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005642 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5643 ALOGV("%s: bus device set volume called", __func__);
5644 if (!out->standby)
5645 ret = out_set_pcm_volume(stream, left, right);
5646 out->volume_l = left;
5647 out->volume_r = right;
5648 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005649 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005651 return -ENOSYS;
5652}
5653
Zhou Songc9672822017-08-16 16:01:39 +08005654static void update_frames_written(struct stream_out *out, size_t bytes)
5655{
5656 size_t bpf = 0;
5657
5658 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5659 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5660 bpf = 1;
5661 else if (!is_offload_usecase(out->usecase))
5662 bpf = audio_bytes_per_sample(out->format) *
5663 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005664
5665 pthread_mutex_lock(&out->position_query_lock);
5666 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005667 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005668 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5669 }
5670 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005671}
5672
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005673int split_and_write_audio_haptic_data(struct stream_out *out,
5674 const void *buffer, size_t bytes_to_write)
5675{
5676 struct audio_device *adev = out->dev;
5677
5678 int ret = 0;
5679 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5680 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5681 size_t frame_size = channel_count * bytes_per_sample;
5682 size_t frame_count = bytes_to_write / frame_size;
5683
5684 bool force_haptic_path =
5685 property_get_bool("vendor.audio.test_haptic", false);
5686
5687 // extract Haptics data from Audio buffer
5688 bool alloc_haptic_buffer = false;
5689 int haptic_channel_count = adev->haptics_config.channels;
5690 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5691 size_t audio_frame_size = frame_size - haptic_frame_size;
5692 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5693
5694 if (adev->haptic_buffer == NULL) {
5695 alloc_haptic_buffer = true;
5696 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5697 free(adev->haptic_buffer);
5698 adev->haptic_buffer_size = 0;
5699 alloc_haptic_buffer = true;
5700 }
5701
5702 if (alloc_haptic_buffer) {
5703 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005704 if(adev->haptic_buffer == NULL) {
5705 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5706 return -ENOMEM;
5707 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005708 adev->haptic_buffer_size = total_haptic_buffer_size;
5709 }
5710
5711 size_t src_index = 0, aud_index = 0, hap_index = 0;
5712 uint8_t *audio_buffer = (uint8_t *)buffer;
5713 uint8_t *haptic_buffer = adev->haptic_buffer;
5714
5715 // This is required for testing only. This works for stereo data only.
5716 // One channel is fed to audio stream and other to haptic stream for testing.
5717 if (force_haptic_path)
5718 audio_frame_size = haptic_frame_size = bytes_per_sample;
5719
5720 for (size_t i = 0; i < frame_count; i++) {
5721 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5722 audio_frame_size);
5723 aud_index += audio_frame_size;
5724 src_index += audio_frame_size;
5725
5726 if (adev->haptic_pcm)
5727 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5728 haptic_frame_size);
5729 hap_index += haptic_frame_size;
5730 src_index += haptic_frame_size;
5731
5732 // This is required for testing only.
5733 // Discard haptic channel data.
5734 if (force_haptic_path)
5735 src_index += haptic_frame_size;
5736 }
5737
5738 // write to audio pipeline
5739 ret = pcm_write(out->pcm, (void *)audio_buffer,
5740 frame_count * audio_frame_size);
5741
5742 // write to haptics pipeline
5743 if (adev->haptic_pcm)
5744 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5745 frame_count * haptic_frame_size);
5746
5747 return ret;
5748}
5749
Aalique Grahame22e49102018-12-18 14:23:57 -08005750#ifdef NO_AUDIO_OUT
5751static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5752 const void *buffer __unused, size_t bytes)
5753{
5754 struct stream_out *out = (struct stream_out *)stream;
5755
5756 /* No Output device supported other than BT for playback.
5757 * Sleep for the amount of buffer duration
5758 */
5759 lock_output_stream(out);
5760 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5761 (const struct audio_stream_out *)&out->stream) /
5762 out_get_sample_rate(&out->stream.common));
5763 pthread_mutex_unlock(&out->lock);
5764 return bytes;
5765}
5766#endif
5767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005768static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5769 size_t bytes)
5770{
5771 struct stream_out *out = (struct stream_out *)stream;
5772 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005773 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305774 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005775 const size_t frame_size = audio_stream_out_frame_size(stream);
5776 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305777 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005778 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005779
Haynes Mathew George380745d2017-10-04 15:27:45 -07005780 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005781 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305782
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305783 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005784
Dhananjay Kumarac341582017-02-23 23:42:25 +05305785 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305786 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305787 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5788 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005789 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305790 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305791 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305792 ALOGD(" %s: sound card is not active/SSR state", __func__);
5793 ret= -EIO;
5794 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305795 }
5796 }
5797
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305798 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305799 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305800 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305801 goto exit;
5802 }
5803
Haynes Mathew George16081042017-05-31 17:16:49 -07005804 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5805 ret = -EINVAL;
5806 goto exit;
5807 }
5808
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005809 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305810 !out->is_iec61937_info_available) {
5811
5812 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5813 out->is_iec61937_info_available = true;
5814 } else if (audio_extn_passthru_is_enabled()) {
5815 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305816 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305817
5818 if((out->format == AUDIO_FORMAT_DTS) ||
5819 (out->format == AUDIO_FORMAT_DTS_HD)) {
5820 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5821 buffer, bytes);
5822 if (ret) {
5823 if (ret != -ENOSYS) {
5824 out->is_iec61937_info_available = false;
5825 ALOGD("iec61937 transmission info not yet updated retry");
5826 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305827 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305828 /* if stream has started and after that there is
5829 * stream config change (iec transmission config)
5830 * then trigger select_device to update backend configuration.
5831 */
5832 out->stream_config_changed = true;
5833 pthread_mutex_lock(&adev->lock);
5834 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305835 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005836 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305837 ret = -EINVAL;
5838 goto exit;
5839 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305840 pthread_mutex_unlock(&adev->lock);
5841 out->stream_config_changed = false;
5842 out->is_iec61937_info_available = true;
5843 }
5844 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305845
Meng Wang4c32fb42020-01-16 17:57:11 +08005846#ifdef AUDIO_GKI_ENABLED
5847 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5848 compr_passthr = out->compr_config.codec->reserved[0];
5849#else
5850 compr_passthr = out->compr_config.codec->compr_passthr;
5851#endif
5852
Garmond Leung317cbf12017-09-13 16:20:50 -07005853 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005854 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305855 (out->is_iec61937_info_available == true)) {
5856 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5857 ret = -EINVAL;
5858 goto exit;
5859 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305860 }
5861 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305862
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005863 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005864 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005865 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5866 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305867 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305868 ret = -EIO;
5869 goto exit;
5870 }
5871 }
5872 }
5873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005874 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005875 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005876 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5877
Eric Laurent150dbfe2013-02-27 14:31:02 -08005878 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005879 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5880 ret = voice_extn_compress_voip_start_output_stream(out);
5881 else
5882 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005883 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005884 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005885 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005886 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887 goto exit;
5888 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305889 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005890 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005891
5892 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005893 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005894 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305895 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005896 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005897 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305898
5899 if ((out->is_iec61937_info_available == true) &&
5900 (audio_extn_passthru_is_passthrough_stream(out))&&
5901 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5902 ret = -EINVAL;
5903 goto exit;
5904 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305905 if (out->set_dual_mono)
5906 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005907
5908 // log startup time in ms.
5909 simple_stats_log(
5910 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005911 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005912
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005913 if (adev->is_channel_status_set == false &&
5914 compare_device_type(&out->device_list,
5915 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005916 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305917 adev->is_channel_status_set = true;
5918 }
5919
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305920 if ((adev->use_old_pspd_mix_ctrl == true) &&
5921 (out->pspd_coeff_sent == false)) {
5922 /*
5923 * Need to resend pspd coefficients after stream started for
5924 * older kernel version as it does not save the coefficients
5925 * and also stream has to be started for coeff to apply.
5926 */
5927 usecase = get_usecase_from_list(adev, out->usecase);
5928 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305929 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305930 out->pspd_coeff_sent = true;
5931 }
5932 }
5933
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005934 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005935 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005936 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005937 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005938 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5939 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305940 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5941 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005942 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305943 out->send_next_track_params = false;
5944 out->is_compr_metadata_avail = false;
5945 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005946 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305947 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305948 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005949
Ashish Jain83a6cc22016-06-28 14:34:17 +05305950 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305951 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305952 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305953 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005954 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305955 return -EINVAL;
5956 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305957 audio_format_t dst_format = out->hal_op_format;
5958 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305959
Dieter Luecking5d57def2018-09-07 14:23:37 +02005960 /* prevent division-by-zero */
5961 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5962 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5963 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5964 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305965 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005966 ATRACE_END();
5967 return -EINVAL;
5968 }
5969
Ashish Jainf1eaa582016-05-23 20:54:24 +05305970 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5971 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5972
Ashish Jain83a6cc22016-06-28 14:34:17 +05305973 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305974 dst_format,
5975 buffer,
5976 src_format,
5977 frames);
5978
Ashish Jain83a6cc22016-06-28 14:34:17 +05305979 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305980 bytes_to_write);
5981
5982 /*Convert written bytes in audio flinger format*/
5983 if (ret > 0)
5984 ret = ((ret * format_to_bitwidth_table[out->format]) /
5985 format_to_bitwidth_table[dst_format]);
5986 }
5987 } else
5988 ret = compress_write(out->compr, buffer, bytes);
5989
Zhou Songc9672822017-08-16 16:01:39 +08005990 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5991 update_frames_written(out, bytes);
5992
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305993 if (ret < 0)
5994 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005995 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305996 /*msg to cb thread only if non blocking write is enabled*/
5997 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305998 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005999 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306000 } else if (-ENETRESET == ret) {
6001 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306002 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306003 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306004 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006005 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306006 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006007 }
Ashish Jain5106d362016-05-11 19:23:33 +05306008
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306009 /* Call compr start only when non-zero bytes of data is there to be rendered */
6010 if (!out->playback_started && ret > 0) {
6011 int status = compress_start(out->compr);
6012 if (status < 0) {
6013 ret = status;
6014 ALOGE("%s: compr start failed with err %d", __func__, errno);
6015 goto exit;
6016 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006017 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006019 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006020 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006021 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006022
6023 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6024 popcount(out->channel_mask),
6025 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006026 }
6027 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006028 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006029 return ret;
6030 } else {
6031 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006032 size_t bytes_to_write = bytes;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006033 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006034 if (out->muted)
6035 memset((void *)buffer, 0, bytes);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006036 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006037 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6038 __func__, frames, frame_size, bytes_to_write);
6039
Aalique Grahame22e49102018-12-18 14:23:57 -08006040 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006041 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6042 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6043 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006044 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6045 int16_t *src = (int16_t *)buffer;
6046 int16_t *dst = (int16_t *)buffer;
6047
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006048 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006049 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006050 "out_write called for %s use case with wrong properties",
6051 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006052
6053 /*
6054 * FIXME: this can be removed once audio flinger mixer supports
6055 * mono output
6056 */
6057
6058 /*
6059 * Code below goes over each frame in the buffer and adds both
6060 * L and R samples and then divides by 2 to convert to mono
6061 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006062 if (channel_count == 2) {
6063 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6064 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6065 }
6066 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006067 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006068 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006069
6070 // Note: since out_get_presentation_position() is called alternating with out_write()
6071 // by AudioFlinger, we can check underruns using the prior timestamp read.
6072 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6073 if (out->last_fifo_valid) {
6074 // compute drain to see if there is an underrun.
6075 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306076 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6077 int64_t frames_by_time =
6078 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6079 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006080 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6081
6082 if (underrun > 0) {
6083 simple_stats_log(&out->fifo_underruns, underrun);
6084
6085 ALOGW("%s: underrun(%lld) "
6086 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6087 __func__,
6088 (long long)out->fifo_underruns.n,
6089 (long long)frames_by_time,
6090 (long long)out->last_fifo_frames_remaining);
6091 }
6092 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6093 }
6094
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306095 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006096
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006097 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006098
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006099 if (out->config.rate)
6100 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6101 out->config.rate;
6102
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006103 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006104 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6105
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006106 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006107 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006108 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306109 out->convert_buffer != NULL) {
6110
6111 memcpy_by_audio_format(out->convert_buffer,
6112 out->hal_op_format,
6113 buffer,
6114 out->hal_ip_format,
6115 out->config.period_size * out->config.channels);
6116
6117 ret = pcm_write(out->pcm, out->convert_buffer,
6118 (out->config.period_size *
6119 out->config.channels *
6120 format_to_bitwidth_table[out->hal_op_format]));
6121 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306122 /*
6123 * To avoid underrun in DSP when the application is not pumping
6124 * data at required rate, check for the no. of bytes and ignore
6125 * pcm_write if it is less than actual buffer size.
6126 * It is a work around to a change in compress VOIP driver.
6127 */
6128 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6129 bytes < (out->config.period_size * out->config.channels *
6130 audio_bytes_per_sample(out->format))) {
6131 size_t voip_buf_size =
6132 out->config.period_size * out->config.channels *
6133 audio_bytes_per_sample(out->format);
6134 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6135 __func__, bytes, voip_buf_size);
6136 usleep(((uint64_t)voip_buf_size - bytes) *
6137 1000000 / audio_stream_out_frame_size(stream) /
6138 out_get_sample_rate(&out->stream.common));
6139 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006140 } else {
6141 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6142 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6143 else
6144 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6145 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306146 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006147
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006148 release_out_focus(out);
6149
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306150 if (ret < 0)
6151 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006152 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306153 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155 }
6156
6157exit:
Zhou Songc9672822017-08-16 16:01:39 +08006158 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306159 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306160 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006162 pthread_mutex_unlock(&out->lock);
6163
6164 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006165 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006166 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306167 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306168 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306169 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306170 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306171 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306172 out->standby = true;
6173 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306174 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006175 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6176 /* prevent division-by-zero */
6177 uint32_t stream_size = audio_stream_out_frame_size(stream);
6178 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006179
Dieter Luecking5d57def2018-09-07 14:23:37 +02006180 if ((stream_size == 0) || (srate == 0)) {
6181 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6182 ATRACE_END();
6183 return -EINVAL;
6184 }
6185 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6186 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006187 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306188 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006189 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006190 return ret;
6191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006192 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006193 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006194 return bytes;
6195}
6196
6197static int out_get_render_position(const struct audio_stream_out *stream,
6198 uint32_t *dsp_frames)
6199{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006200 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006201
6202 if (dsp_frames == NULL)
6203 return -EINVAL;
6204
6205 *dsp_frames = 0;
6206 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006207 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306208
6209 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6210 * this operation and adev_close_output_stream(where out gets reset).
6211 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306212 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006213 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306214 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006215 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306216 return 0;
6217 }
6218
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006219 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306220 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306221 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006222 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306223 if (ret < 0)
6224 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006225 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306226 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006227 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306228 if (-ENETRESET == ret) {
6229 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306230 out->card_status = CARD_STATUS_OFFLINE;
6231 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306232 } else if(ret < 0) {
6233 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306234 ret = -EINVAL;
6235 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306236 /*
6237 * Handle corner case where compress session is closed during SSR
6238 * and timestamp is queried
6239 */
6240 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306241 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306242 } else if (out->prev_card_status_offline) {
6243 ALOGE("ERROR: previously sound card was offline,return error");
6244 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306245 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306246 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006247 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306248 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306249 pthread_mutex_unlock(&out->lock);
6250 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006251 } else if (audio_is_linear_pcm(out->format)) {
6252 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006253 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006254 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006255 } else
6256 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257}
6258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006259static int out_add_audio_effect(const struct audio_stream *stream __unused,
6260 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261{
6262 return 0;
6263}
6264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006265static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6266 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006267{
6268 return 0;
6269}
6270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006271static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6272 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306274 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006275}
6276
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006277static int out_get_presentation_position(const struct audio_stream_out *stream,
6278 uint64_t *frames, struct timespec *timestamp)
6279{
6280 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306281 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006282 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006283
Ashish Jain5106d362016-05-11 19:23:33 +05306284 /* below piece of code is not guarded against any lock because audioFliner serializes
6285 * this operation and adev_close_output_stream( where out gets reset).
6286 */
6287 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306288 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006289 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306290 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6291 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6292 return 0;
6293 }
6294
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006295 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006296
Ashish Jain5106d362016-05-11 19:23:33 +05306297 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6298 ret = compress_get_tstamp(out->compr, &dsp_frames,
6299 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006300 // Adjustment accounts for A2dp encoder latency with offload usecases
6301 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006302 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006303 unsigned long offset =
6304 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6305 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6306 }
Ashish Jain5106d362016-05-11 19:23:33 +05306307 ALOGVV("%s rendered frames %ld sample_rate %d",
6308 __func__, dsp_frames, out->sample_rate);
6309 *frames = dsp_frames;
6310 if (ret < 0)
6311 ret = -errno;
6312 if (-ENETRESET == ret) {
6313 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306314 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306315 ret = -EINVAL;
6316 } else
6317 ret = 0;
6318 /* this is the best we can do */
6319 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006320 } else {
6321 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006322 unsigned int avail;
6323 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006324 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006325 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006326
Andy Hunga1f48fa2019-07-01 18:14:53 -07006327 if (out->kernel_buffer_size > avail) {
6328 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6329 } else {
6330 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6331 __func__, avail, out->kernel_buffer_size);
6332 avail = out->kernel_buffer_size;
6333 frames_temp = out->last_fifo_frames_remaining = 0;
6334 }
6335 out->last_fifo_valid = true;
6336 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6337
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006338 if (out->written >= frames_temp)
6339 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006340
Andy Hunga1f48fa2019-07-01 18:14:53 -07006341 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6342 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6343
Weiyin Jiangd4633762018-03-16 12:05:03 +08006344 // This adjustment accounts for buffering after app processor.
6345 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006346 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006347 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006348 if (signed_frames >= frames_temp)
6349 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006350
Weiyin Jiangd4633762018-03-16 12:05:03 +08006351 // Adjustment accounts for A2dp encoder latency with non offload usecases
6352 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006353 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006354 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6355 if (signed_frames >= frames_temp)
6356 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006357 }
6358
6359 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006360 *frames = signed_frames;
6361 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006362 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006363 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6364 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006365 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306366 *frames = out->written;
6367 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306368 if (is_offload_usecase(out->usecase))
6369 ret = -EINVAL;
6370 else
6371 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006372 }
6373 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006374 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006375 return ret;
6376}
6377
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006378static int out_set_callback(struct audio_stream_out *stream,
6379 stream_callback_t callback, void *cookie)
6380{
6381 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006382 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006383
6384 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006385 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006386 out->client_callback = callback;
6387 out->client_cookie = cookie;
6388 if (out->adsp_hdlr_stream_handle) {
6389 ret = audio_extn_adsp_hdlr_stream_set_callback(
6390 out->adsp_hdlr_stream_handle,
6391 callback,
6392 cookie);
6393 if (ret)
6394 ALOGW("%s:adsp hdlr callback registration failed %d",
6395 __func__, ret);
6396 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006397 pthread_mutex_unlock(&out->lock);
6398 return 0;
6399}
6400
6401static int out_pause(struct audio_stream_out* stream)
6402{
6403 struct stream_out *out = (struct stream_out *)stream;
6404 int status = -ENOSYS;
6405 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006406 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006407 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306408 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006409 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006410 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006411 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306412 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306413 status = compress_pause(out->compr);
6414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006415 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006416
Mingming Yin21854652016-04-13 11:54:02 -07006417 if (audio_extn_passthru_is_active()) {
6418 ALOGV("offload use case, pause passthru");
6419 audio_extn_passthru_on_pause(out);
6420 }
6421
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306422 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006423 audio_extn_dts_notify_playback_state(out->usecase, 0,
6424 out->sample_rate, popcount(out->channel_mask),
6425 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006426 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006427 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006428 pthread_mutex_unlock(&out->lock);
6429 }
6430 return status;
6431}
6432
6433static int out_resume(struct audio_stream_out* stream)
6434{
6435 struct stream_out *out = (struct stream_out *)stream;
6436 int status = -ENOSYS;
6437 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006438 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006439 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306440 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006441 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006442 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006443 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306444 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306445 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006446 }
6447 if (!status) {
6448 out->offload_state = OFFLOAD_STATE_PLAYING;
6449 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306450 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006451 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6452 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006453 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006454 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455 pthread_mutex_unlock(&out->lock);
6456 }
6457 return status;
6458}
6459
6460static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6461{
6462 struct stream_out *out = (struct stream_out *)stream;
6463 int status = -ENOSYS;
6464 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006465 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006466 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006467 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6468 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6469 else
6470 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6471 pthread_mutex_unlock(&out->lock);
6472 }
6473 return status;
6474}
6475
6476static int out_flush(struct audio_stream_out* stream)
6477{
6478 struct stream_out *out = (struct stream_out *)stream;
6479 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006480 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006481 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006482 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006483 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006484 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6485 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006486 } else {
6487 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6488 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006489 out->written = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006490 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006491 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006492 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006493 return 0;
6494 }
6495 return -ENOSYS;
6496}
6497
Haynes Mathew George16081042017-05-31 17:16:49 -07006498static int out_stop(const struct audio_stream_out* stream)
6499{
6500 struct stream_out *out = (struct stream_out *)stream;
6501 struct audio_device *adev = out->dev;
6502 int ret = -ENOSYS;
6503
6504 ALOGV("%s", __func__);
6505 pthread_mutex_lock(&adev->lock);
6506 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6507 out->playback_started && out->pcm != NULL) {
6508 pcm_stop(out->pcm);
6509 ret = stop_output_stream(out);
6510 out->playback_started = false;
6511 }
6512 pthread_mutex_unlock(&adev->lock);
6513 return ret;
6514}
6515
6516static int out_start(const struct audio_stream_out* stream)
6517{
6518 struct stream_out *out = (struct stream_out *)stream;
6519 struct audio_device *adev = out->dev;
6520 int ret = -ENOSYS;
6521
6522 ALOGV("%s", __func__);
6523 pthread_mutex_lock(&adev->lock);
6524 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6525 !out->playback_started && out->pcm != NULL) {
6526 ret = start_output_stream(out);
6527 if (ret == 0) {
6528 out->playback_started = true;
6529 }
6530 }
6531 pthread_mutex_unlock(&adev->lock);
6532 return ret;
6533}
6534
6535/*
6536 * Modify config->period_count based on min_size_frames
6537 */
6538static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6539{
6540 int periodCountRequested = (min_size_frames + config->period_size - 1)
6541 / config->period_size;
6542 int periodCount = MMAP_PERIOD_COUNT_MIN;
6543
6544 ALOGV("%s original config.period_size = %d config.period_count = %d",
6545 __func__, config->period_size, config->period_count);
6546
6547 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6548 periodCount *= 2;
6549 }
6550 config->period_count = periodCount;
6551
6552 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6553}
6554
Phil Burkfe17efd2019-03-25 10:23:35 -07006555// Read offset for the positional timestamp from a persistent vendor property.
6556// This is to workaround apparent inaccuracies in the timing information that
6557// is used by the AAudio timing model. The inaccuracies can cause glitches.
6558static int64_t get_mmap_out_time_offset() {
6559 const int32_t kDefaultOffsetMicros = 0;
6560 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006561 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006562 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6563 return mmap_time_offset_micros * (int64_t)1000;
6564}
6565
Haynes Mathew George16081042017-05-31 17:16:49 -07006566static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6567 int32_t min_size_frames,
6568 struct audio_mmap_buffer_info *info)
6569{
6570 struct stream_out *out = (struct stream_out *)stream;
6571 struct audio_device *adev = out->dev;
6572 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006573 unsigned int offset1 = 0;
6574 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006575 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006576 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006577 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006578
Arun Mirpuri5d170872019-03-26 13:21:31 -07006579 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306580 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006581 pthread_mutex_lock(&adev->lock);
6582
Sharad Sanglec6f32552018-05-04 16:15:38 +05306583 if (CARD_STATUS_OFFLINE == out->card_status ||
6584 CARD_STATUS_OFFLINE == adev->card_status) {
6585 ALOGW("out->card_status or adev->card_status offline, try again");
6586 ret = -EIO;
6587 goto exit;
6588 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306589 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006590 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6591 ret = -EINVAL;
6592 goto exit;
6593 }
6594 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6595 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6596 ret = -ENOSYS;
6597 goto exit;
6598 }
6599 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6600 if (out->pcm_device_id < 0) {
6601 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6602 __func__, out->pcm_device_id, out->usecase);
6603 ret = -EINVAL;
6604 goto exit;
6605 }
6606
6607 adjust_mmap_period_count(&out->config, min_size_frames);
6608
Arun Mirpuri5d170872019-03-26 13:21:31 -07006609 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006610 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6611 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6612 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306613 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306614 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6615 out->card_status = CARD_STATUS_OFFLINE;
6616 adev->card_status = CARD_STATUS_OFFLINE;
6617 ret = -EIO;
6618 goto exit;
6619 }
6620
Haynes Mathew George16081042017-05-31 17:16:49 -07006621 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6622 step = "open";
6623 ret = -ENODEV;
6624 goto exit;
6625 }
6626 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6627 if (ret < 0) {
6628 step = "begin";
6629 goto exit;
6630 }
juyuchen626833d2019-06-04 16:48:02 +08006631
6632 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006633 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006634 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006635 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006636 ret = platform_get_mmap_data_fd(adev->platform,
6637 out->pcm_device_id, 0 /*playback*/,
6638 &info->shared_memory_fd,
6639 &mmap_size);
6640 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006641 // Fall back to non exclusive mode
6642 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6643 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006644 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6645 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6646
Arun Mirpuri5d170872019-03-26 13:21:31 -07006647 if (mmap_size < buffer_size) {
6648 step = "mmap";
6649 goto exit;
6650 }
juyuchen626833d2019-06-04 16:48:02 +08006651 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006652 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006653 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006654 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006655
6656 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6657 if (ret < 0) {
6658 step = "commit";
6659 goto exit;
6660 }
6661
Phil Burkfe17efd2019-03-25 10:23:35 -07006662 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6663
Haynes Mathew George16081042017-05-31 17:16:49 -07006664 out->standby = false;
6665 ret = 0;
6666
Arun Mirpuri5d170872019-03-26 13:21:31 -07006667 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006668 __func__, info->shared_memory_address, info->buffer_size_frames);
6669
6670exit:
6671 if (ret != 0) {
6672 if (out->pcm == NULL) {
6673 ALOGE("%s: %s - %d", __func__, step, ret);
6674 } else {
6675 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6676 pcm_close(out->pcm);
6677 out->pcm = NULL;
6678 }
6679 }
6680 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306681 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006682 return ret;
6683}
6684
6685static int out_get_mmap_position(const struct audio_stream_out *stream,
6686 struct audio_mmap_position *position)
6687{
6688 struct stream_out *out = (struct stream_out *)stream;
6689 ALOGVV("%s", __func__);
6690 if (position == NULL) {
6691 return -EINVAL;
6692 }
6693 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006694 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006695 return -ENOSYS;
6696 }
6697 if (out->pcm == NULL) {
6698 return -ENOSYS;
6699 }
6700
6701 struct timespec ts = { 0, 0 };
6702 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6703 if (ret < 0) {
6704 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6705 return ret;
6706 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006707 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6708 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006709 return 0;
6710}
6711
6712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006713/** audio_stream_in implementation **/
6714static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6715{
6716 struct stream_in *in = (struct stream_in *)stream;
6717
6718 return in->config.rate;
6719}
6720
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006721static int in_set_sample_rate(struct audio_stream *stream __unused,
6722 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723{
6724 return -ENOSYS;
6725}
6726
6727static size_t in_get_buffer_size(const struct audio_stream *stream)
6728{
6729 struct stream_in *in = (struct stream_in *)stream;
6730
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006731 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6732 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006733 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6734 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306735 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306736 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006737
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006738 return in->config.period_size * in->af_period_multiplier *
6739 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006740}
6741
6742static uint32_t in_get_channels(const struct audio_stream *stream)
6743{
6744 struct stream_in *in = (struct stream_in *)stream;
6745
6746 return in->channel_mask;
6747}
6748
6749static audio_format_t in_get_format(const struct audio_stream *stream)
6750{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006751 struct stream_in *in = (struct stream_in *)stream;
6752
6753 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006754}
6755
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006756static int in_set_format(struct audio_stream *stream __unused,
6757 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006758{
6759 return -ENOSYS;
6760}
6761
6762static int in_standby(struct audio_stream *stream)
6763{
6764 struct stream_in *in = (struct stream_in *)stream;
6765 struct audio_device *adev = in->dev;
6766 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306767 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6768 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006769 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306770
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006771 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006772 if (!in->standby && in->is_st_session) {
6773 ALOGD("%s: sound trigger pcm stop lab", __func__);
6774 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006775 if (adev->num_va_sessions > 0)
6776 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006777 in->standby = 1;
6778 }
6779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006780 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006781 if (adev->adm_deregister_stream)
6782 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6783
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006784 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006786 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006787 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006788 voice_extn_compress_voip_close_input_stream(stream);
6789 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006790 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6791 do_stop = in->capture_started;
6792 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006793 if (in->mmap_shared_memory_fd >= 0) {
6794 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6795 __func__, in->mmap_shared_memory_fd);
6796 close(in->mmap_shared_memory_fd);
6797 in->mmap_shared_memory_fd = -1;
6798 }
Zhou Songa8895042016-07-05 17:54:22 +08006799 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306800 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306801 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006802 }
6803
Arun Mirpuri5d170872019-03-26 13:21:31 -07006804 if (in->pcm) {
6805 ATRACE_BEGIN("pcm_in_close");
6806 pcm_close(in->pcm);
6807 ATRACE_END();
6808 in->pcm = NULL;
6809 }
6810
Carter Hsu2e429db2019-05-14 18:50:52 +08006811 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006812 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006813
George Gao3018ede2019-10-23 13:23:00 -07006814 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6815 if (adev->num_va_sessions > 0)
6816 adev->num_va_sessions--;
6817 }
Quinn Malef6050362019-01-30 15:55:40 -08006818
Eric Laurent150dbfe2013-02-27 14:31:02 -08006819 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006820 }
6821 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006822 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006823 return status;
6824}
6825
Aalique Grahame22e49102018-12-18 14:23:57 -08006826static int in_dump(const struct audio_stream *stream,
6827 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006828{
Aalique Grahame22e49102018-12-18 14:23:57 -08006829 struct stream_in *in = (struct stream_in *)stream;
6830
6831 // We try to get the lock for consistency,
6832 // but it isn't necessary for these variables.
6833 // If we're not in standby, we may be blocked on a read.
6834 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6835 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6836 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6837 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6838
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006839 char buffer[256]; // for statistics formatting
6840 if (in->start_latency_ms.n > 0) {
6841 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6842 dprintf(fd, " Start latency ms: %s\n", buffer);
6843 }
6844
Aalique Grahame22e49102018-12-18 14:23:57 -08006845 if (locked) {
6846 pthread_mutex_unlock(&in->lock);
6847 }
6848
6849 // dump error info
6850 (void)error_log_dump(
6851 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006853 return 0;
6854}
6855
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306856static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6857{
6858 if (!stream || !parms)
6859 return;
6860
6861 struct stream_in *in = (struct stream_in *)stream;
6862 struct audio_device *adev = in->dev;
6863
6864 card_status_t status;
6865 int card;
6866 if (parse_snd_card_status(parms, &card, &status) < 0)
6867 return;
6868
6869 pthread_mutex_lock(&adev->lock);
6870 bool valid_cb = (card == adev->snd_card);
6871 pthread_mutex_unlock(&adev->lock);
6872
6873 if (!valid_cb)
6874 return;
6875
6876 lock_input_stream(in);
6877 if (in->card_status != status)
6878 in->card_status = status;
6879 pthread_mutex_unlock(&in->lock);
6880
6881 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6882 use_case_table[in->usecase],
6883 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6884
6885 // a better solution would be to report error back to AF and let
6886 // it put the stream to standby
6887 if (status == CARD_STATUS_OFFLINE)
6888 in_standby(&in->stream.common);
6889
6890 return;
6891}
6892
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006893int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006894 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006895 audio_source_t source)
6896{
6897 struct audio_device *adev = in->dev;
6898 int ret = 0;
6899
6900 lock_input_stream(in);
6901 pthread_mutex_lock(&adev->lock);
6902
6903 /* no audio source uses val == 0 */
6904 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6905 in->source = source;
6906 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6907 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6908 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6909 (in->config.rate == 8000 || in->config.rate == 16000 ||
6910 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6911 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6912 ret = voice_extn_compress_voip_open_input_stream(in);
6913 if (ret != 0) {
6914 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6915 __func__, ret);
6916 }
6917 }
6918 }
6919
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006920 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6921 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006922 // Workaround: If routing to an non existing usb device, fail gracefully
6923 // The routing request will otherwise block during 10 second
6924 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006925 struct str_parms *usb_addr =
6926 str_parms_create_str(get_usb_device_address(devices));
6927 if (is_usb_in_device_type(devices) && usb_addr &&
6928 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006929 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6930 ret = -ENOSYS;
6931 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006932 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006933 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006934 if (!in->standby && !in->is_st_session) {
6935 ALOGV("update input routing change");
6936 // inform adm before actual routing to prevent glitches.
6937 if (adev->adm_on_routing_change) {
6938 adev->adm_on_routing_change(adev->adm_data,
6939 in->capture_handle);
6940 ret = select_devices(adev, in->usecase);
6941 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6942 adev->adm_routing_changed = true;
6943 }
6944 }
6945 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006946 if (usb_addr)
6947 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006948 }
6949 pthread_mutex_unlock(&adev->lock);
6950 pthread_mutex_unlock(&in->lock);
6951
6952 ALOGD("%s: exit: status(%d)", __func__, ret);
6953 return ret;
6954}
6955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006956static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6957{
6958 struct stream_in *in = (struct stream_in *)stream;
6959 struct audio_device *adev = in->dev;
6960 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306962 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006963
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306964 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006965 parms = str_parms_create_str(kvpairs);
6966
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306967 if (!parms)
6968 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006969 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006970 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006971
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306972 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6973 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306974 strlcpy(in->profile, value, sizeof(in->profile));
6975 ALOGV("updating stream profile with value '%s'", in->profile);
6976 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6977 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006978 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306979 in->sample_rate, in->bit_width,
6980 in->profile, &in->app_type_cfg);
6981 }
6982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006983 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006984 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006985
6986 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306987error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306988 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006989}
6990
6991static char* in_get_parameters(const struct audio_stream *stream,
6992 const char *keys)
6993{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006994 struct stream_in *in = (struct stream_in *)stream;
6995 struct str_parms *query = str_parms_create_str(keys);
6996 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006997 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006998
6999 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007000 if (reply) {
7001 str_parms_destroy(reply);
7002 }
7003 if (query) {
7004 str_parms_destroy(query);
7005 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007006 ALOGE("in_get_parameters: failed to create query or reply");
7007 return NULL;
7008 }
7009
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007010 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007011
7012 voice_extn_in_get_parameters(in, query, reply);
7013
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007014 stream_get_parameter_channels(query, reply,
7015 &in->supported_channel_masks[0]);
7016 stream_get_parameter_formats(query, reply,
7017 &in->supported_formats[0]);
7018 stream_get_parameter_rates(query, reply,
7019 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007020 str = str_parms_to_str(reply);
7021 str_parms_destroy(query);
7022 str_parms_destroy(reply);
7023
7024 ALOGV("%s: exit: returns - %s", __func__, str);
7025 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007026}
7027
Aalique Grahame22e49102018-12-18 14:23:57 -08007028static int in_set_gain(struct audio_stream_in *stream,
7029 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007030{
Aalique Grahame22e49102018-12-18 14:23:57 -08007031 struct stream_in *in = (struct stream_in *)stream;
7032 char mixer_ctl_name[128];
7033 struct mixer_ctl *ctl;
7034 int ctl_value;
7035
7036 ALOGV("%s: gain %f", __func__, gain);
7037
7038 if (stream == NULL)
7039 return -EINVAL;
7040
7041 /* in_set_gain() only used to silence MMAP capture for now */
7042 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7043 return -ENOSYS;
7044
7045 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7046
7047 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7048 if (!ctl) {
7049 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7050 __func__, mixer_ctl_name);
7051 return -ENOSYS;
7052 }
7053
7054 if (gain < RECORD_GAIN_MIN)
7055 gain = RECORD_GAIN_MIN;
7056 else if (gain > RECORD_GAIN_MAX)
7057 gain = RECORD_GAIN_MAX;
7058 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7059
7060 mixer_ctl_set_value(ctl, 0, ctl_value);
7061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 return 0;
7063}
7064
7065static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7066 size_t bytes)
7067{
7068 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307069
7070 if (in == NULL) {
7071 ALOGE("%s: stream_in ptr is NULL", __func__);
7072 return -EINVAL;
7073 }
7074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007075 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307076 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307077 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007078
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007079 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307080
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007081 if (in->is_st_session) {
7082 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7083 /* Read from sound trigger HAL */
7084 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007085 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007086 if (adev->num_va_sessions < UINT_MAX)
7087 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007088 in->standby = 0;
7089 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007090 pthread_mutex_unlock(&in->lock);
7091 return bytes;
7092 }
7093
Haynes Mathew George16081042017-05-31 17:16:49 -07007094 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7095 ret = -ENOSYS;
7096 goto exit;
7097 }
7098
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007099 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7100 !in->standby && adev->adm_routing_changed) {
7101 ret = -ENOSYS;
7102 goto exit;
7103 }
7104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007105 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007106 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7107
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007108 pthread_mutex_lock(&adev->lock);
7109 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7110 ret = voice_extn_compress_voip_start_input_stream(in);
7111 else
7112 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007113 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7114 if (adev->num_va_sessions < UINT_MAX)
7115 adev->num_va_sessions++;
7116 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007117 pthread_mutex_unlock(&adev->lock);
7118 if (ret != 0) {
7119 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007120 }
7121 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007122
7123 // log startup time in ms.
7124 simple_stats_log(
7125 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007127
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307128 /* Avoid read if capture_stopped is set */
7129 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7130 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7131 ret = -EINVAL;
7132 goto exit;
7133 }
7134
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007135 // what's the duration requested by the client?
7136 long ns = 0;
7137
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307138 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007139 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7140 in->config.rate;
7141
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007142 ret = request_in_focus(in, ns);
7143 if (ret != 0)
7144 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007145 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007146
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307147 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307148 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7149 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307150 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007151 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307152 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007153 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007154 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007155 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007156 } else if (audio_extn_ffv_get_stream() == in) {
7157 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307158 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007159 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307160 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7161 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7162 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7163 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307164 ret = -EINVAL;
7165 goto exit;
7166 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307167 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307168 ret = -errno;
7169 }
7170 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307171 /* bytes read is always set to bytes for non compress usecases */
7172 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007173 }
7174
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007175 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 /*
Quinn Malef6050362019-01-30 15:55:40 -08007178 * Instead of writing zeroes here, we could trust the hardware to always
7179 * provide zeroes when muted. This is also muted with voice recognition
7180 * usecases so that other clients do not have access to voice recognition
7181 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007182 */
Quinn Malef6050362019-01-30 15:55:40 -08007183 if ((ret == 0 && voice_get_mic_mute(adev) &&
7184 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007185 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7186 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007187 (adev->num_va_sessions &&
7188 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7189 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7190 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007191 memset(buffer, 0, bytes);
7192
7193exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307194 frame_size = audio_stream_in_frame_size(stream);
7195 if (frame_size > 0)
7196 in->frames_read += bytes_read/frame_size;
7197
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007198 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307199 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007200 pthread_mutex_unlock(&in->lock);
7201
7202 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307203 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307204 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307205 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307206 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307207 in->standby = true;
7208 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307209 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307210 bytes_read = bytes;
7211 memset(buffer, 0, bytes);
7212 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007214 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7215 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007216 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307217 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307218 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007219 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307220 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007221}
7222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007223static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224{
7225 return 0;
7226}
7227
Aalique Grahame22e49102018-12-18 14:23:57 -08007228static int in_get_capture_position(const struct audio_stream_in *stream,
7229 int64_t *frames, int64_t *time)
7230{
7231 if (stream == NULL || frames == NULL || time == NULL) {
7232 return -EINVAL;
7233 }
7234 struct stream_in *in = (struct stream_in *)stream;
7235 int ret = -ENOSYS;
7236
7237 lock_input_stream(in);
7238 // note: ST sessions do not close the alsa pcm driver synchronously
7239 // on standby. Therefore, we may return an error even though the
7240 // pcm stream is still opened.
7241 if (in->standby) {
7242 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7243 "%s stream in standby but pcm not NULL for non ST session", __func__);
7244 goto exit;
7245 }
7246 if (in->pcm) {
7247 struct timespec timestamp;
7248 unsigned int avail;
7249 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7250 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007251 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007252 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007253 ret = 0;
7254 }
7255 }
7256exit:
7257 pthread_mutex_unlock(&in->lock);
7258 return ret;
7259}
7260
Carter Hsu2e429db2019-05-14 18:50:52 +08007261static int in_update_effect_list(bool add, effect_handle_t effect,
7262 struct listnode *head)
7263{
7264 struct listnode *node;
7265 struct in_effect_list *elist = NULL;
7266 struct in_effect_list *target = NULL;
7267 int ret = 0;
7268
7269 if (!head)
7270 return ret;
7271
7272 list_for_each(node, head) {
7273 elist = node_to_item(node, struct in_effect_list, list);
7274 if (elist->handle == effect) {
7275 target = elist;
7276 break;
7277 }
7278 }
7279
7280 if (add) {
7281 if (target) {
7282 ALOGD("effect %p already exist", effect);
7283 return ret;
7284 }
7285
7286 target = (struct in_effect_list *)
7287 calloc(1, sizeof(struct in_effect_list));
7288
7289 if (!target) {
7290 ALOGE("%s:fail to allocate memory", __func__);
7291 return -ENOMEM;
7292 }
7293
7294 target->handle = effect;
7295 list_add_tail(head, &target->list);
7296 } else {
7297 if (target) {
7298 list_remove(&target->list);
7299 free(target);
7300 }
7301 }
7302
7303 return ret;
7304}
7305
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007306static int add_remove_audio_effect(const struct audio_stream *stream,
7307 effect_handle_t effect,
7308 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007309{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007310 struct stream_in *in = (struct stream_in *)stream;
7311 int status = 0;
7312 effect_descriptor_t desc;
7313
7314 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007315 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7316
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007317 if (status != 0)
7318 return status;
7319
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007320 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007321 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007322 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007323 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7324 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007325 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007326
7327 in_update_effect_list(enable, effect, &in->aec_list);
7328 enable = !list_empty(&in->aec_list);
7329 if (enable == in->enable_aec)
7330 goto exit;
7331
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007332 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007333 ALOGD("AEC enable %d", enable);
7334
Aalique Grahame22e49102018-12-18 14:23:57 -08007335 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7336 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7337 in->dev->enable_voicerx = enable;
7338 struct audio_usecase *usecase;
7339 struct listnode *node;
7340 list_for_each(node, &in->dev->usecase_list) {
7341 usecase = node_to_item(node, struct audio_usecase, list);
7342 if (usecase->type == PCM_PLAYBACK)
7343 select_devices(in->dev, usecase->id);
7344 }
7345 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007346 if (!in->standby) {
7347 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7348 select_devices(in->dev, in->usecase);
7349 }
7350
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007351 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007352 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7353
7354 in_update_effect_list(enable, effect, &in->ns_list);
7355 enable = !list_empty(&in->ns_list);
7356 if (enable == in->enable_ns)
7357 goto exit;
7358
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007359 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007360 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007361 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007362 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7363 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007364 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7365 select_devices(in->dev, in->usecase);
7366 } else
7367 select_devices(in->dev, in->usecase);
7368 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007369 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007370exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007371 pthread_mutex_unlock(&in->dev->lock);
7372 pthread_mutex_unlock(&in->lock);
7373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007374 return 0;
7375}
7376
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007377static int in_add_audio_effect(const struct audio_stream *stream,
7378 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007379{
Eric Laurent994a6932013-07-17 11:51:42 -07007380 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007381 return add_remove_audio_effect(stream, effect, true);
7382}
7383
7384static int in_remove_audio_effect(const struct audio_stream *stream,
7385 effect_handle_t effect)
7386{
Eric Laurent994a6932013-07-17 11:51:42 -07007387 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007388 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007389}
7390
Derek Chenf939fb72018-11-13 13:34:41 -08007391streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7392 audio_io_handle_t input)
7393{
7394 struct listnode *node;
7395
7396 list_for_each(node, &dev->active_inputs_list) {
7397 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7398 streams_input_ctxt_t,
7399 list);
7400 if (in_ctxt->input->capture_handle == input) {
7401 return in_ctxt;
7402 }
7403 }
7404 return NULL;
7405}
7406
7407streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7408 audio_io_handle_t output)
7409{
7410 struct listnode *node;
7411
7412 list_for_each(node, &dev->active_outputs_list) {
7413 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7414 streams_output_ctxt_t,
7415 list);
7416 if (out_ctxt->output->handle == output) {
7417 return out_ctxt;
7418 }
7419 }
7420 return NULL;
7421}
7422
Haynes Mathew George16081042017-05-31 17:16:49 -07007423static int in_stop(const struct audio_stream_in* stream)
7424{
7425 struct stream_in *in = (struct stream_in *)stream;
7426 struct audio_device *adev = in->dev;
7427
7428 int ret = -ENOSYS;
7429 ALOGV("%s", __func__);
7430 pthread_mutex_lock(&adev->lock);
7431 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7432 in->capture_started && in->pcm != NULL) {
7433 pcm_stop(in->pcm);
7434 ret = stop_input_stream(in);
7435 in->capture_started = false;
7436 }
7437 pthread_mutex_unlock(&adev->lock);
7438 return ret;
7439}
7440
7441static int in_start(const struct audio_stream_in* stream)
7442{
7443 struct stream_in *in = (struct stream_in *)stream;
7444 struct audio_device *adev = in->dev;
7445 int ret = -ENOSYS;
7446
7447 ALOGV("%s in %p", __func__, in);
7448 pthread_mutex_lock(&adev->lock);
7449 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7450 !in->capture_started && in->pcm != NULL) {
7451 if (!in->capture_started) {
7452 ret = start_input_stream(in);
7453 if (ret == 0) {
7454 in->capture_started = true;
7455 }
7456 }
7457 }
7458 pthread_mutex_unlock(&adev->lock);
7459 return ret;
7460}
7461
Phil Burke0a86d12019-02-16 22:28:11 -08007462// Read offset for the positional timestamp from a persistent vendor property.
7463// This is to workaround apparent inaccuracies in the timing information that
7464// is used by the AAudio timing model. The inaccuracies can cause glitches.
7465static int64_t in_get_mmap_time_offset() {
7466 const int32_t kDefaultOffsetMicros = 0;
7467 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007468 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007469 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7470 return mmap_time_offset_micros * (int64_t)1000;
7471}
7472
Haynes Mathew George16081042017-05-31 17:16:49 -07007473static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7474 int32_t min_size_frames,
7475 struct audio_mmap_buffer_info *info)
7476{
7477 struct stream_in *in = (struct stream_in *)stream;
7478 struct audio_device *adev = in->dev;
7479 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007480 unsigned int offset1 = 0;
7481 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007482 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007483 uint32_t mmap_size = 0;
7484 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007485
7486 pthread_mutex_lock(&adev->lock);
7487 ALOGV("%s in %p", __func__, in);
7488
Sharad Sanglec6f32552018-05-04 16:15:38 +05307489 if (CARD_STATUS_OFFLINE == in->card_status||
7490 CARD_STATUS_OFFLINE == adev->card_status) {
7491 ALOGW("in->card_status or adev->card_status offline, try again");
7492 ret = -EIO;
7493 goto exit;
7494 }
7495
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307496 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007497 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7498 ret = -EINVAL;
7499 goto exit;
7500 }
7501 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7502 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7503 ALOGV("%s in %p", __func__, in);
7504 ret = -ENOSYS;
7505 goto exit;
7506 }
7507 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7508 if (in->pcm_device_id < 0) {
7509 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7510 __func__, in->pcm_device_id, in->usecase);
7511 ret = -EINVAL;
7512 goto exit;
7513 }
7514
7515 adjust_mmap_period_count(&in->config, min_size_frames);
7516
7517 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7518 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7519 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7520 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307521 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307522 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7523 in->card_status = CARD_STATUS_OFFLINE;
7524 adev->card_status = CARD_STATUS_OFFLINE;
7525 ret = -EIO;
7526 goto exit;
7527 }
7528
Haynes Mathew George16081042017-05-31 17:16:49 -07007529 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7530 step = "open";
7531 ret = -ENODEV;
7532 goto exit;
7533 }
7534
7535 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7536 if (ret < 0) {
7537 step = "begin";
7538 goto exit;
7539 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007540
juyuchen626833d2019-06-04 16:48:02 +08007541 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007542 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7543 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7544 info->burst_size_frames = in->config.period_size;
7545 ret = platform_get_mmap_data_fd(adev->platform,
7546 in->pcm_device_id, 1 /*capture*/,
7547 &info->shared_memory_fd,
7548 &mmap_size);
7549 if (ret < 0) {
7550 // Fall back to non exclusive mode
7551 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7552 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007553 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7554 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7555
Arun Mirpuri5d170872019-03-26 13:21:31 -07007556 if (mmap_size < buffer_size) {
7557 step = "mmap";
7558 goto exit;
7559 }
juyuchen626833d2019-06-04 16:48:02 +08007560 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007561 }
7562
7563 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007564
7565 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7566 if (ret < 0) {
7567 step = "commit";
7568 goto exit;
7569 }
7570
Phil Burke0a86d12019-02-16 22:28:11 -08007571 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7572
Haynes Mathew George16081042017-05-31 17:16:49 -07007573 in->standby = false;
7574 ret = 0;
7575
7576 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7577 __func__, info->shared_memory_address, info->buffer_size_frames);
7578
7579exit:
7580 if (ret != 0) {
7581 if (in->pcm == NULL) {
7582 ALOGE("%s: %s - %d", __func__, step, ret);
7583 } else {
7584 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7585 pcm_close(in->pcm);
7586 in->pcm = NULL;
7587 }
7588 }
7589 pthread_mutex_unlock(&adev->lock);
7590 return ret;
7591}
7592
7593static int in_get_mmap_position(const struct audio_stream_in *stream,
7594 struct audio_mmap_position *position)
7595{
7596 struct stream_in *in = (struct stream_in *)stream;
7597 ALOGVV("%s", __func__);
7598 if (position == NULL) {
7599 return -EINVAL;
7600 }
7601 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7602 return -ENOSYS;
7603 }
7604 if (in->pcm == NULL) {
7605 return -ENOSYS;
7606 }
7607 struct timespec ts = { 0, 0 };
7608 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7609 if (ret < 0) {
7610 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7611 return ret;
7612 }
Phil Burke0a86d12019-02-16 22:28:11 -08007613 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7614 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007615 return 0;
7616}
7617
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307618static int in_get_active_microphones(const struct audio_stream_in *stream,
7619 struct audio_microphone_characteristic_t *mic_array,
7620 size_t *mic_count) {
7621 struct stream_in *in = (struct stream_in *)stream;
7622 struct audio_device *adev = in->dev;
7623 ALOGVV("%s", __func__);
7624
7625 lock_input_stream(in);
7626 pthread_mutex_lock(&adev->lock);
7627 int ret = platform_get_active_microphones(adev->platform,
7628 audio_channel_count_from_in_mask(in->channel_mask),
7629 in->usecase, mic_array, mic_count);
7630 pthread_mutex_unlock(&adev->lock);
7631 pthread_mutex_unlock(&in->lock);
7632
7633 return ret;
7634}
7635
7636static int adev_get_microphones(const struct audio_hw_device *dev,
7637 struct audio_microphone_characteristic_t *mic_array,
7638 size_t *mic_count) {
7639 struct audio_device *adev = (struct audio_device *)dev;
7640 ALOGVV("%s", __func__);
7641
7642 pthread_mutex_lock(&adev->lock);
7643 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7644 pthread_mutex_unlock(&adev->lock);
7645
7646 return ret;
7647}
juyuchendb308c22019-01-21 11:57:17 -07007648
7649static void in_update_sink_metadata(struct audio_stream_in *stream,
7650 const struct sink_metadata *sink_metadata) {
7651
7652 if (stream == NULL
7653 || sink_metadata == NULL
7654 || sink_metadata->tracks == NULL) {
7655 return;
7656 }
7657
7658 int error = 0;
7659 struct stream_in *in = (struct stream_in *)stream;
7660 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007661 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007662 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007663
7664 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007665
7666 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007667 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007668
7669 lock_input_stream(in);
7670 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007671 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007672
Zhou Song62ea0282020-03-22 19:53:01 +08007673 is_ha_usecase = adev->ha_proxy_enable ?
7674 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7675 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7676 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007677 && adev->voice_tx_output != NULL) {
7678 /* Use the rx device from afe-proxy record to route voice call because
7679 there is no routing if tx device is on primary hal and rx device
7680 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007681 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007682
7683 if (!voice_is_call_state_active(adev)) {
7684 if (adev->mode == AUDIO_MODE_IN_CALL) {
7685 adev->current_call_output = adev->voice_tx_output;
7686 error = voice_start_call(adev);
7687 if (error != 0)
7688 ALOGE("%s: start voice call failed %d", __func__, error);
7689 }
7690 } else {
7691 adev->current_call_output = adev->voice_tx_output;
7692 voice_update_devices_for_all_voice_usecases(adev);
7693 }
7694 }
7695
7696 pthread_mutex_unlock(&adev->lock);
7697 pthread_mutex_unlock(&in->lock);
7698}
7699
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307700int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007701 audio_io_handle_t handle,
7702 audio_devices_t devices,
7703 audio_output_flags_t flags,
7704 struct audio_config *config,
7705 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007706 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007707{
7708 struct audio_device *adev = (struct audio_device *)dev;
7709 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307710 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007711 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007712 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307713 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007714 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7715 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7716 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7717 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007718 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007719 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7720 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007721 bool force_haptic_path =
7722 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007723 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007724#ifdef AUDIO_GKI_ENABLED
7725 __s32 *generic_dec;
7726#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007727
kunleizdff872d2018-08-20 14:40:33 +08007728 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007729 is_usb_dev = false;
7730 devices = AUDIO_DEVICE_OUT_SPEAKER;
7731 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7732 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007733 if (config->format == AUDIO_FORMAT_DEFAULT)
7734 config->format = AUDIO_FORMAT_PCM_16_BIT;
7735 if (config->sample_rate == 0)
7736 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7737 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7738 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007739 }
7740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007741 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307742
Rahul Sharma99770982019-03-06 17:05:26 +05307743 pthread_mutex_lock(&adev->lock);
7744 if (out_get_stream(adev, handle) != NULL) {
7745 ALOGW("%s, output stream already opened", __func__);
7746 ret = -EEXIST;
7747 }
7748 pthread_mutex_unlock(&adev->lock);
7749 if (ret)
7750 return ret;
7751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007752 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7753
Mingming Yin3a941d42016-02-17 18:08:05 -08007754 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007755 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7756 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307757
7758
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007759 if (!out) {
7760 return -ENOMEM;
7761 }
7762
Haynes Mathew George204045b2015-02-25 20:32:03 -08007763 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007764 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007765 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007766 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007767 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007769 if (devices == AUDIO_DEVICE_NONE)
7770 devices = AUDIO_DEVICE_OUT_SPEAKER;
7771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007772 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007773 list_init(&out->device_list);
7774 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007775 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007776 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007777 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307778 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307779 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7780 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7781 else
7782 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007783 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007784 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007785 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307786 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307787 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307788 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007789 out->hal_output_suspend_supported = 0;
7790 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307791 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307792 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307793 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007794 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007795
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307796 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307797 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007798 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7799
Aalique Grahame22e49102018-12-18 14:23:57 -08007800 if (direct_dev &&
7801 (audio_is_linear_pcm(out->format) ||
7802 config->format == AUDIO_FORMAT_DEFAULT) &&
7803 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7804 audio_format_t req_format = config->format;
7805 audio_channel_mask_t req_channel_mask = config->channel_mask;
7806 uint32_t req_sample_rate = config->sample_rate;
7807
7808 pthread_mutex_lock(&adev->lock);
7809 if (is_hdmi) {
7810 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7811 ret = read_hdmi_sink_caps(out);
7812 if (config->sample_rate == 0)
7813 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7814 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7815 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7816 if (config->format == AUDIO_FORMAT_DEFAULT)
7817 config->format = AUDIO_FORMAT_PCM_16_BIT;
7818 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007819 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7820 &config->format,
7821 &out->supported_formats[0],
7822 MAX_SUPPORTED_FORMATS,
7823 &config->channel_mask,
7824 &out->supported_channel_masks[0],
7825 MAX_SUPPORTED_CHANNEL_MASKS,
7826 &config->sample_rate,
7827 &out->supported_sample_rates[0],
7828 MAX_SUPPORTED_SAMPLE_RATES);
7829 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007830 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007831
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007832 pthread_mutex_unlock(&adev->lock);
7833 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007834 if (ret == -ENOSYS) {
7835 /* ignore and go with default */
7836 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007837 }
7838 // For MMAP NO IRQ, allow conversions in ADSP
7839 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7840 goto error_open;
7841 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007842 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007843 goto error_open;
7844 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007845
7846 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7847 config->sample_rate = req_sample_rate;
7848 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7849 config->channel_mask = req_channel_mask;
7850 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7851 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007852 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007853
7854 out->sample_rate = config->sample_rate;
7855 out->channel_mask = config->channel_mask;
7856 out->format = config->format;
7857 if (is_hdmi) {
7858 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7859 out->config = pcm_config_hdmi_multi;
7860 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7861 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7862 out->config = pcm_config_mmap_playback;
7863 out->stream.start = out_start;
7864 out->stream.stop = out_stop;
7865 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7866 out->stream.get_mmap_position = out_get_mmap_position;
7867 } else {
7868 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7869 out->config = pcm_config_hifi;
7870 }
7871
7872 out->config.rate = out->sample_rate;
7873 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7874 if (is_hdmi) {
7875 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7876 audio_bytes_per_sample(out->format));
7877 }
7878 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007879 }
7880
Derek Chenf6318be2017-06-12 17:16:24 -04007881 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007882 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007883 /* extract car audio stream index */
7884 out->car_audio_stream =
7885 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7886 if (out->car_audio_stream < 0) {
7887 ALOGE("%s: invalid car audio stream %x",
7888 __func__, out->car_audio_stream);
7889 ret = -EINVAL;
7890 goto error_open;
7891 }
Derek Chen5f67a942020-02-24 23:08:13 -08007892 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007893 }
7894
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007895 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007896 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007897 if (!voice_extn_is_compress_voip_supported()) {
7898 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7899 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007900 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307901 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007902 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7903 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007904 out->volume_l = INVALID_OUT_VOLUME;
7905 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007906
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007907 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007908 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007909 uint32_t channel_count =
7910 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307911 out->config.channels = channel_count;
7912
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007913 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7914 out->sample_rate, out->format,
7915 channel_count, false);
7916 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7917 if (frame_size != 0)
7918 out->config.period_size = buffer_size / frame_size;
7919 else
7920 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007921 }
7922 } else {
7923 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7924 voice_extn_compress_voip_is_active(out->dev)) &&
7925 (voice_extn_compress_voip_is_config_supported(config))) {
7926 ret = voice_extn_compress_voip_open_output_stream(out);
7927 if (ret != 0) {
7928 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7929 __func__, ret);
7930 goto error_open;
7931 }
Sujin Panicker19027262019-09-16 18:28:06 +05307932 } else {
7933 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7934 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007935 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007936 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007937 } else if (audio_is_linear_pcm(out->format) &&
7938 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7939 out->channel_mask = config->channel_mask;
7940 out->sample_rate = config->sample_rate;
7941 out->format = config->format;
7942 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7943 // does this change?
7944 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7945 out->config.rate = config->sample_rate;
7946 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7947 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7948 audio_bytes_per_sample(config->format));
7949 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007950 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307951 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307952 pthread_mutex_lock(&adev->lock);
7953 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7954 pthread_mutex_unlock(&adev->lock);
7955
7956 // reject offload during card offline to allow
7957 // fallback to s/w paths
7958 if (offline) {
7959 ret = -ENODEV;
7960 goto error_open;
7961 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007962
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007963 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7964 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7965 ALOGE("%s: Unsupported Offload information", __func__);
7966 ret = -EINVAL;
7967 goto error_open;
7968 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007969
Atul Khare3fa6e542017-08-09 00:56:17 +05307970 if (config->offload_info.format == 0)
7971 config->offload_info.format = config->format;
7972 if (config->offload_info.sample_rate == 0)
7973 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007974
Mingming Yin90310102013-11-13 16:57:00 -08007975 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307976 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007977 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007978 ret = -EINVAL;
7979 goto error_open;
7980 }
7981
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007982 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7983 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7984 (audio_extn_passthru_is_passthrough_stream(out)) &&
7985 !((config->sample_rate == 48000) ||
7986 (config->sample_rate == 96000) ||
7987 (config->sample_rate == 192000))) {
7988 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7989 __func__, config->sample_rate, config->offload_info.format);
7990 ret = -EINVAL;
7991 goto error_open;
7992 }
7993
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007994 out->compr_config.codec = (struct snd_codec *)
7995 calloc(1, sizeof(struct snd_codec));
7996
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007997 if (!out->compr_config.codec) {
7998 ret = -ENOMEM;
7999 goto error_open;
8000 }
8001
Dhananjay Kumarac341582017-02-23 23:42:25 +05308002 out->stream.pause = out_pause;
8003 out->stream.resume = out_resume;
8004 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308005 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308006 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008007 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308008 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008009 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308010 } else {
8011 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8012 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008013 }
vivek mehta446c3962015-09-14 10:57:35 -07008014
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308015 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8016 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008017#ifdef AUDIO_GKI_ENABLED
8018 /* out->compr_config.codec->reserved[1] is for flags */
8019 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8020#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308021 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008022#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308023 }
8024
vivek mehta446c3962015-09-14 10:57:35 -07008025 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008026 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008027 config->format == 0 && config->sample_rate == 0 &&
8028 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008029 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008030 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8031 } else {
8032 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8033 ret = -EEXIST;
8034 goto error_open;
8035 }
vivek mehta446c3962015-09-14 10:57:35 -07008036 }
8037
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008038 if (config->offload_info.channel_mask)
8039 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008040 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008041 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008042 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008043 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308044 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008045 ret = -EINVAL;
8046 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008047 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008048
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008049 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 out->sample_rate = config->offload_info.sample_rate;
8051
Mingming Yin3ee55c62014-08-04 14:23:35 -07008052 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008053
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308054 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308055 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308056 audio_extn_dolby_send_ddp_endp_params(adev);
8057 audio_extn_dolby_set_dmid(adev);
8058 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008060 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008061 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008062 out->compr_config.codec->bit_rate =
8063 config->offload_info.bit_rate;
8064 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308065 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008066 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308067 /* Update bit width only for non passthrough usecases.
8068 * For passthrough usecases, the output will always be opened @16 bit
8069 */
8070 if (!audio_extn_passthru_is_passthrough_stream(out))
8071 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308072
8073 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008074#ifdef AUDIO_GKI_ENABLED
8075 /* out->compr_config.codec->reserved[1] is for flags */
8076 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8077 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8078#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308079 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8080 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008081#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308082
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008083 /*TODO: Do we need to change it for passthrough */
8084 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008085
Manish Dewangana6fc5442015-08-24 20:30:31 +05308086 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8087 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308088 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308089 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308090 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8091 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308092
8093 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8094 AUDIO_FORMAT_PCM) {
8095
8096 /*Based on platform support, configure appropriate alsa format for corresponding
8097 *hal input format.
8098 */
8099 out->compr_config.codec->format = hal_format_to_alsa(
8100 config->offload_info.format);
8101
Ashish Jain83a6cc22016-06-28 14:34:17 +05308102 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308103 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308104 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308105
Dhananjay Kumarac341582017-02-23 23:42:25 +05308106 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308107 *hal input format and alsa format might differ based on platform support.
8108 */
8109 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308110 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308111
8112 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8113
Deeraj Soman93155a62019-09-30 19:00:37 +05308114 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8115 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8116 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8117 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8118 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308119
Ashish Jainf1eaa582016-05-23 20:54:24 +05308120 /* Check if alsa session is configured with the same format as HAL input format,
8121 * if not then derive correct fragment size needed to accomodate the
8122 * conversion of HAL input format to alsa format.
8123 */
8124 audio_extn_utils_update_direct_pcm_fragment_size(out);
8125
8126 /*if hal input and output fragment size is different this indicates HAL input format is
8127 *not same as the alsa format
8128 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308129 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308130 /*Allocate a buffer to convert input data to the alsa configured format.
8131 *size of convert buffer is equal to the size required to hold one fragment size
8132 *worth of pcm data, this is because flinger does not write more than fragment_size
8133 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308134 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8135 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308136 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8137 ret = -ENOMEM;
8138 goto error_open;
8139 }
8140 }
8141 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8142 out->compr_config.fragment_size =
8143 audio_extn_passthru_get_buffer_size(&config->offload_info);
8144 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8145 } else {
8146 out->compr_config.fragment_size =
8147 platform_get_compress_offload_buffer_size(&config->offload_info);
8148 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8149 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008150
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308151 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8152 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8153 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008154 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8155#ifdef AUDIO_GKI_ENABLED
8156 generic_dec =
8157 &(out->compr_config.codec->options.generic.reserved[1]);
8158 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8159 AUDIO_OUTPUT_BIT_WIDTH;
8160#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308161 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008162#endif
8163 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008164
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308165 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8166 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8167 }
8168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008169 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8170 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008171
Manish Dewangan69426c82017-01-30 17:35:36 +05308172 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8173 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8174 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8175 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8176 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8177 } else {
8178 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8179 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008180
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308181 memset(&out->channel_map_param, 0,
8182 sizeof(struct audio_out_channel_map_param));
8183
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008184 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308185 out->send_next_track_params = false;
8186 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008187 out->offload_state = OFFLOAD_STATE_IDLE;
8188 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008189 out->writeAt.tv_sec = 0;
8190 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008191
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008192 audio_extn_dts_create_state_notifier_node(out->usecase);
8193
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008194 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8195 __func__, config->offload_info.version,
8196 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308197
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308198 /* Check if DSD audio format is supported in codec
8199 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308200 */
8201
8202 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308203 (!platform_check_codec_dsd_support(adev->platform) ||
8204 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308205 ret = -EINVAL;
8206 goto error_open;
8207 }
8208
Ashish Jain5106d362016-05-11 19:23:33 +05308209 /* Disable gapless if any of the following is true
8210 * passthrough playback
8211 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308212 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308213 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308214 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308215 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008216 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308217 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308218 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308219 check_and_set_gapless_mode(adev, false);
8220 } else
8221 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008222
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308223 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008224 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8225 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308226 if (config->format == AUDIO_FORMAT_DSD) {
8227 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008228#ifdef AUDIO_GKI_ENABLED
8229 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8230 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8231#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308232 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008233#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308234 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008235
8236 create_offload_callback_thread(out);
8237
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008238 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008239 switch (config->sample_rate) {
8240 case 0:
8241 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8242 break;
8243 case 8000:
8244 case 16000:
8245 case 48000:
8246 out->sample_rate = config->sample_rate;
8247 break;
8248 default:
8249 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8250 config->sample_rate);
8251 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8252 ret = -EINVAL;
8253 goto error_open;
8254 }
8255 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8256 switch (config->channel_mask) {
8257 case AUDIO_CHANNEL_NONE:
8258 case AUDIO_CHANNEL_OUT_STEREO:
8259 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8260 break;
8261 default:
8262 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8263 config->channel_mask);
8264 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8265 ret = -EINVAL;
8266 goto error_open;
8267 }
8268 switch (config->format) {
8269 case AUDIO_FORMAT_DEFAULT:
8270 case AUDIO_FORMAT_PCM_16_BIT:
8271 out->format = AUDIO_FORMAT_PCM_16_BIT;
8272 break;
8273 default:
8274 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8275 config->format);
8276 config->format = AUDIO_FORMAT_PCM_16_BIT;
8277 ret = -EINVAL;
8278 goto error_open;
8279 }
8280
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308281 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008282 if (ret != 0) {
8283 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008284 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008285 goto error_open;
8286 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008287 } else if (is_single_device_type_equal(&out->device_list,
8288 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008289 switch (config->sample_rate) {
8290 case 0:
8291 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8292 break;
8293 case 8000:
8294 case 16000:
8295 case 48000:
8296 out->sample_rate = config->sample_rate;
8297 break;
8298 default:
8299 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8300 config->sample_rate);
8301 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8302 ret = -EINVAL;
8303 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008304 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008305 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8306 switch (config->channel_mask) {
8307 case AUDIO_CHANNEL_NONE:
8308 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8309 break;
8310 case AUDIO_CHANNEL_OUT_STEREO:
8311 out->channel_mask = config->channel_mask;
8312 break;
8313 default:
8314 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8315 config->channel_mask);
8316 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8317 ret = -EINVAL;
8318 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008319 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008320 switch (config->format) {
8321 case AUDIO_FORMAT_DEFAULT:
8322 out->format = AUDIO_FORMAT_PCM_16_BIT;
8323 break;
8324 case AUDIO_FORMAT_PCM_16_BIT:
8325 out->format = config->format;
8326 break;
8327 default:
8328 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8329 config->format);
8330 config->format = AUDIO_FORMAT_PCM_16_BIT;
8331 ret = -EINVAL;
8332 break;
8333 }
8334 if (ret != 0)
8335 goto error_open;
8336
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008337 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8338 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008339 out->config.rate = out->sample_rate;
8340 out->config.channels =
8341 audio_channel_count_from_out_mask(out->channel_mask);
8342 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008343 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008344 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308345 unsigned int channels = 0;
8346 /*Update config params to default if not set by the caller*/
8347 if (config->sample_rate == 0)
8348 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8349 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8350 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8351 if (config->format == AUDIO_FORMAT_DEFAULT)
8352 config->format = AUDIO_FORMAT_PCM_16_BIT;
8353
8354 channels = audio_channel_count_from_out_mask(out->channel_mask);
8355
Varun Balaraje49253e2017-07-06 19:48:56 +05308356 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8357 out->usecase = get_interactive_usecase(adev);
8358 out->config = pcm_config_low_latency;
8359 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308360 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008361 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8362 out->flags);
8363 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008364 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8365 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8366 out->config = pcm_config_mmap_playback;
8367 out->stream.start = out_start;
8368 out->stream.stop = out_stop;
8369 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8370 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308371 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8372 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008373 out->hal_output_suspend_supported =
8374 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8375 out->dynamic_pm_qos_config_supported =
8376 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8377 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008378 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8379 } else {
8380 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8381 //the mixer path will be a string similar to "low-latency-playback resume"
8382 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8383 strlcat(out->pm_qos_mixer_path,
8384 " resume", MAX_MIXER_PATH_LEN);
8385 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8386 out->pm_qos_mixer_path);
8387 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308388 out->config = pcm_config_low_latency;
8389 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8390 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8391 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308392 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8393 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8394 if (out->config.period_size <= 0) {
8395 ALOGE("Invalid configuration period size is not valid");
8396 ret = -EINVAL;
8397 goto error_open;
8398 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008399 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8400 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8401 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008402 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8403 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8404 out->config = pcm_config_haptics_audio;
8405 if (force_haptic_path)
8406 adev->haptics_config = pcm_config_haptics_audio;
8407 else
8408 adev->haptics_config = pcm_config_haptics;
8409
Meng Wangd08ce322020-04-02 08:59:20 +08008410 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008411 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8412
8413 if (force_haptic_path) {
8414 out->config.channels = 1;
8415 adev->haptics_config.channels = 1;
8416 } else
8417 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 -08008418 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008419 ret = audio_extn_auto_hal_open_output_stream(out);
8420 if (ret) {
8421 ALOGE("%s: Failed to open output stream for bus device", __func__);
8422 ret = -EINVAL;
8423 goto error_open;
8424 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308425 } else {
8426 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008427 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8428 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308429 }
8430 out->hal_ip_format = format = out->format;
8431 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8432 out->hal_op_format = pcm_format_to_hal(out->config.format);
8433 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8434 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008435 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308436 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308437 if (out->hal_ip_format != out->hal_op_format) {
8438 uint32_t buffer_size = out->config.period_size *
8439 format_to_bitwidth_table[out->hal_op_format] *
8440 out->config.channels;
8441 out->convert_buffer = calloc(1, buffer_size);
8442 if (out->convert_buffer == NULL){
8443 ALOGE("Allocation failed for convert buffer for size %d",
8444 out->compr_config.fragment_size);
8445 ret = -ENOMEM;
8446 goto error_open;
8447 }
8448 ALOGD("Convert buffer allocated of size %d", buffer_size);
8449 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008450 }
8451
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008452 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8453 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308454
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008455 /* TODO remove this hardcoding and check why width is zero*/
8456 if (out->bit_width == 0)
8457 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308458 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008459 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008460 &out->device_list, out->flags,
8461 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308462 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308463 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008464 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008465 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8466 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008467 if(adev->primary_output == NULL)
8468 adev->primary_output = out;
8469 else {
8470 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008471 ret = -EEXIST;
8472 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008473 }
8474 }
8475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008476 /* Check if this usecase is already existing */
8477 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008478 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8479 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008480 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008481 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008482 ret = -EEXIST;
8483 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008484 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008486 pthread_mutex_unlock(&adev->lock);
8487
8488 out->stream.common.get_sample_rate = out_get_sample_rate;
8489 out->stream.common.set_sample_rate = out_set_sample_rate;
8490 out->stream.common.get_buffer_size = out_get_buffer_size;
8491 out->stream.common.get_channels = out_get_channels;
8492 out->stream.common.get_format = out_get_format;
8493 out->stream.common.set_format = out_set_format;
8494 out->stream.common.standby = out_standby;
8495 out->stream.common.dump = out_dump;
8496 out->stream.common.set_parameters = out_set_parameters;
8497 out->stream.common.get_parameters = out_get_parameters;
8498 out->stream.common.add_audio_effect = out_add_audio_effect;
8499 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8500 out->stream.get_latency = out_get_latency;
8501 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008502#ifdef NO_AUDIO_OUT
8503 out->stream.write = out_write_for_no_output;
8504#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008506#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008507 out->stream.get_render_position = out_get_render_position;
8508 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008509 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008510
Haynes Mathew George16081042017-05-31 17:16:49 -07008511 if (out->realtime)
8512 out->af_period_multiplier = af_period_multiplier;
8513 else
8514 out->af_period_multiplier = 1;
8515
Andy Hunga1f48fa2019-07-01 18:14:53 -07008516 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008519 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008520 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008521
8522 config->format = out->stream.common.get_format(&out->stream.common);
8523 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8524 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308525 register_format(out->format, out->supported_formats);
8526 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8527 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008528
Aalique Grahame22e49102018-12-18 14:23:57 -08008529 out->error_log = error_log_create(
8530 ERROR_LOG_ENTRIES,
8531 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8532
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308533 /*
8534 By locking output stream before registering, we allow the callback
8535 to update stream's state only after stream's initial state is set to
8536 adev state.
8537 */
8538 lock_output_stream(out);
8539 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8540 pthread_mutex_lock(&adev->lock);
8541 out->card_status = adev->card_status;
8542 pthread_mutex_unlock(&adev->lock);
8543 pthread_mutex_unlock(&out->lock);
8544
Aalique Grahame22e49102018-12-18 14:23:57 -08008545 stream_app_type_cfg_init(&out->app_type_cfg);
8546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008547 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308548 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008549 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008550
8551 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8552 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8553 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008554 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308555 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008556 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008557 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308558 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8559 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008560 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8561 out->usecase, PCM_PLAYBACK);
8562 hdlr_stream_cfg.flags = out->flags;
8563 hdlr_stream_cfg.type = PCM_PLAYBACK;
8564 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8565 &hdlr_stream_cfg);
8566 if (ret) {
8567 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8568 out->adsp_hdlr_stream_handle = NULL;
8569 }
8570 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308571 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8572 is_direct_passthough, false);
8573 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8574 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008575 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008576 if (ret < 0) {
8577 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8578 out->ip_hdlr_handle = NULL;
8579 }
8580 }
Derek Chenf939fb72018-11-13 13:34:41 -08008581
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008582 ret = io_streams_map_insert(adev, &out->stream.common,
8583 out->handle, AUDIO_PATCH_HANDLE_NONE);
8584 if (ret != 0)
8585 goto error_open;
8586
Derek Chenf939fb72018-11-13 13:34:41 -08008587 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8588 calloc(1, sizeof(streams_output_ctxt_t));
8589 if (out_ctxt == NULL) {
8590 ALOGE("%s fail to allocate output ctxt", __func__);
8591 ret = -ENOMEM;
8592 goto error_open;
8593 }
8594 out_ctxt->output = out;
8595
8596 pthread_mutex_lock(&adev->lock);
8597 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8598 pthread_mutex_unlock(&adev->lock);
8599
Eric Laurent994a6932013-07-17 11:51:42 -07008600 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008601 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008602
8603error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308604 if (out->convert_buffer)
8605 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008606 free(out);
8607 *stream_out = NULL;
8608 ALOGD("%s: exit: ret %d", __func__, ret);
8609 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008610}
8611
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308612void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008613 struct audio_stream_out *stream)
8614{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008615 struct stream_out *out = (struct stream_out *)stream;
8616 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008617 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008618
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008619 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308620
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008621 io_streams_map_remove(adev, out->handle);
8622
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308623 // must deregister from sndmonitor first to prevent races
8624 // between the callback and close_stream
8625 audio_extn_snd_mon_unregister_listener(out);
8626
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008627 /* close adsp hdrl session before standby */
8628 if (out->adsp_hdlr_stream_handle) {
8629 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8630 if (ret)
8631 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8632 out->adsp_hdlr_stream_handle = NULL;
8633 }
8634
Manish Dewangan21a850a2017-08-14 12:03:55 +05308635 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008636 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8637 out->ip_hdlr_handle = NULL;
8638 }
8639
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008640 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308641 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008642 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308643 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308644 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008645 if(ret != 0)
8646 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8647 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008648 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008649 out_standby(&stream->common);
8650
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008651 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008652 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008653 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008654 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008655 if (out->compr_config.codec != NULL)
8656 free(out->compr_config.codec);
8657 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008658
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308659 out->a2dp_compress_mute = false;
8660
Varun Balaraje49253e2017-07-06 19:48:56 +05308661 if (is_interactive_usecase(out->usecase))
8662 free_interactive_usecase(adev, out->usecase);
8663
Ashish Jain83a6cc22016-06-28 14:34:17 +05308664 if (out->convert_buffer != NULL) {
8665 free(out->convert_buffer);
8666 out->convert_buffer = NULL;
8667 }
8668
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008669 if (adev->voice_tx_output == out)
8670 adev->voice_tx_output = NULL;
8671
Aalique Grahame22e49102018-12-18 14:23:57 -08008672 error_log_destroy(out->error_log);
8673 out->error_log = NULL;
8674
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308675 if (adev->primary_output == out)
8676 adev->primary_output = NULL;
8677
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008678 pthread_cond_destroy(&out->cond);
8679 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008680 pthread_mutex_destroy(&out->pre_lock);
8681 pthread_mutex_destroy(&out->latch_lock);
8682 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008683
8684 pthread_mutex_lock(&adev->lock);
8685 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8686 if (out_ctxt != NULL) {
8687 list_remove(&out_ctxt->list);
8688 free(out_ctxt);
8689 } else {
8690 ALOGW("%s, output stream already closed", __func__);
8691 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008692 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008693 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008694 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008695}
8696
8697static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8698{
8699 struct audio_device *adev = (struct audio_device *)dev;
8700 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008701 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008702 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008703 int ret;
8704 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008705 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008706 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008707 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008708
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008709 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008710 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008711
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308712 if (!parms)
8713 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308714
Derek Chen6f293672019-04-01 01:40:24 -07008715 /* notify adev and input/output streams on the snd card status */
8716 adev_snd_mon_cb((void *)adev, parms);
8717
8718 list_for_each(node, &adev->active_outputs_list) {
8719 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8720 streams_output_ctxt_t,
8721 list);
8722 out_snd_mon_cb((void *)out_ctxt->output, parms);
8723 }
8724
8725 list_for_each(node, &adev->active_inputs_list) {
8726 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8727 streams_input_ctxt_t,
8728 list);
8729 in_snd_mon_cb((void *)in_ctxt->input, parms);
8730 }
8731
Zhou Songd6d71752019-05-21 18:08:51 +08008732 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308733 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8734 if (ret >= 0) {
8735 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008736 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308737 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008738 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308739 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008740 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008741 }
8742 }
8743
8744 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008745 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008746 if (!strncmp(value, "false", 5) &&
8747 audio_extn_a2dp_source_is_suspended()) {
8748 struct audio_usecase *usecase;
8749 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008750 list_for_each(node, &adev->usecase_list) {
8751 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008752 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008753 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008754 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008755 reassign_device_list(&usecase->stream.in->device_list,
8756 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008757 select_devices(adev, usecase->id);
8758 }
Zhou Songd6d71752019-05-21 18:08:51 +08008759 }
8760 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308761 }
8762
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008763 status = voice_set_parameters(adev, parms);
8764 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008765 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008767 status = platform_set_parameters(adev->platform, parms);
8768 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008769 goto done;
8770
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008771 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8772 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008773 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008774 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8775 adev->bluetooth_nrec = true;
8776 else
8777 adev->bluetooth_nrec = false;
8778 }
8779
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008780 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8781 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8783 adev->screen_off = false;
8784 else
8785 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008786 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008787 }
8788
Eric Laurent4b084132018-10-19 17:33:43 -07008789 ret = str_parms_get_int(parms, "rotation", &val);
8790 if (ret >= 0) {
8791 bool reverse_speakers = false;
8792 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8793 switch (val) {
8794 // FIXME: note that the code below assumes that the speakers are in the correct placement
8795 // relative to the user when the device is rotated 90deg from its default rotation. This
8796 // assumption is device-specific, not platform-specific like this code.
8797 case 270:
8798 reverse_speakers = true;
8799 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8800 break;
8801 case 0:
8802 case 180:
8803 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8804 break;
8805 case 90:
8806 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8807 break;
8808 default:
8809 ALOGE("%s: unexpected rotation of %d", __func__, val);
8810 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008811 }
Eric Laurent4b084132018-10-19 17:33:43 -07008812 if (status == 0) {
8813 // check and set swap
8814 // - check if orientation changed and speaker active
8815 // - set rotation and cache the rotation value
8816 adev->camera_orientation =
8817 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8818 if (!audio_extn_is_maxx_audio_enabled())
8819 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8820 }
8821 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008822
Mingming Yin514a8bc2014-07-29 15:22:21 -07008823 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8824 if (ret >= 0) {
8825 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8826 adev->bt_wb_speech_enabled = true;
8827 else
8828 adev->bt_wb_speech_enabled = false;
8829 }
8830
Zhou Song12c29502019-03-16 10:37:18 +08008831 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8832 if (ret >= 0) {
8833 val = atoi(value);
8834 adev->swb_speech_mode = val;
8835 }
8836
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008837 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8838 if (ret >= 0) {
8839 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308840 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008841 if (audio_is_output_device(val) &&
8842 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008843 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008844 platform_get_controller_stream_from_params(parms, &controller, &stream);
8845 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8846 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008847 if (ret < 0) {
8848 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308849 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008850 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008851 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308852 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008853 /*
8854 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8855 * Per AudioPolicyManager, USB device is higher priority than WFD.
8856 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8857 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8858 * starting voice call on USB
8859 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008860 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308861 if (ret >= 0)
8862 audio_extn_usb_add_device(device, atoi(value));
8863
Zhou Song6f862822017-11-06 17:27:57 +08008864 if (!audio_extn_usb_is_tunnel_supported()) {
8865 ALOGV("detected USB connect .. disable proxy");
8866 adev->allow_afe_proxy_usage = false;
8867 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008868 }
8869 }
8870
8871 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8872 if (ret >= 0) {
8873 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308874 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008875 /*
8876 * The HDMI / Displayport disconnect handling has been moved to
8877 * audio extension to ensure that its parameters are not
8878 * invalidated prior to updating sysfs of the disconnect event
8879 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8880 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308881 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008882 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308883 if (ret >= 0)
8884 audio_extn_usb_remove_device(device, atoi(value));
8885
Zhou Song6f862822017-11-06 17:27:57 +08008886 if (!audio_extn_usb_is_tunnel_supported()) {
8887 ALOGV("detected USB disconnect .. enable proxy");
8888 adev->allow_afe_proxy_usage = true;
8889 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008890 }
8891 }
8892
Aalique Grahame22e49102018-12-18 14:23:57 -08008893 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008894 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008895
8896 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008897 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308898 struct audio_usecase *usecase;
8899 struct listnode *node;
8900 list_for_each(node, &adev->usecase_list) {
8901 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008902 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8903 continue;
8904
8905 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308906 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308907 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308908 ALOGD("Switching to speaker and muting the stream before select_devices");
8909 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308910 //force device switch to re configure encoder
8911 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308912 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008913 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308914 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008915 out_set_compr_volume(&usecase->stream.out->stream,
8916 usecase->stream.out->volume_l,
8917 usecase->stream.out->volume_r);
8918 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308919 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308920 break;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008921 } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
8922 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8923 if (usecase->stream.out->a2dp_compress_mute) {
8924 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8925 reassign_device_list(&usecase->stream.out->device_list,
8926 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8927 check_a2dp_restore_l(adev, usecase->stream.out, true);
8928 break;
8929 }
8930 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308931 }
8932 }
8933 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008934
8935 //handle vr audio setparam
8936 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8937 value, sizeof(value));
8938 if (ret >= 0) {
8939 ALOGI("Setting vr mode to be %s", value);
8940 if (!strncmp(value, "true", 4)) {
8941 adev->vr_audio_mode_enabled = true;
8942 ALOGI("Setting vr mode to true");
8943 } else if (!strncmp(value, "false", 5)) {
8944 adev->vr_audio_mode_enabled = false;
8945 ALOGI("Setting vr mode to false");
8946 } else {
8947 ALOGI("wrong vr mode set");
8948 }
8949 }
8950
Eric Laurent4b084132018-10-19 17:33:43 -07008951 //FIXME: to be replaced by proper video capture properties API
8952 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8953 if (ret >= 0) {
8954 int camera_facing = CAMERA_FACING_BACK;
8955 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8956 camera_facing = CAMERA_FACING_FRONT;
8957 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8958 camera_facing = CAMERA_FACING_BACK;
8959 else {
8960 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8961 goto done;
8962 }
8963 adev->camera_orientation =
8964 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8965 struct audio_usecase *usecase;
8966 struct listnode *node;
8967 list_for_each(node, &adev->usecase_list) {
8968 usecase = node_to_item(node, struct audio_usecase, list);
8969 struct stream_in *in = usecase->stream.in;
8970 if (usecase->type == PCM_CAPTURE && in != NULL &&
8971 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8972 select_devices(adev, in->usecase);
8973 }
8974 }
8975 }
8976
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308977 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008978done:
8979 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008980 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308981error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008982 ALOGV("%s: exit with code(%d)", __func__, status);
8983 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008984}
8985
8986static char* adev_get_parameters(const struct audio_hw_device *dev,
8987 const char *keys)
8988{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308989 ALOGD("%s:%s", __func__, keys);
8990
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008991 struct audio_device *adev = (struct audio_device *)dev;
8992 struct str_parms *reply = str_parms_create();
8993 struct str_parms *query = str_parms_create_str(keys);
8994 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308995 char value[256] = {0};
8996 int ret = 0;
8997
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008998 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008999 if (reply) {
9000 str_parms_destroy(reply);
9001 }
9002 if (query) {
9003 str_parms_destroy(query);
9004 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009005 ALOGE("adev_get_parameters: failed to create query or reply");
9006 return NULL;
9007 }
9008
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009009 //handle vr audio getparam
9010
9011 ret = str_parms_get_str(query,
9012 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9013 value, sizeof(value));
9014
9015 if (ret >= 0) {
9016 bool vr_audio_enabled = false;
9017 pthread_mutex_lock(&adev->lock);
9018 vr_audio_enabled = adev->vr_audio_mode_enabled;
9019 pthread_mutex_unlock(&adev->lock);
9020
9021 ALOGI("getting vr mode to %d", vr_audio_enabled);
9022
9023 if (vr_audio_enabled) {
9024 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9025 "true");
9026 goto exit;
9027 } else {
9028 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9029 "false");
9030 goto exit;
9031 }
9032 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009033
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009034 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009035 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009036 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009037 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009038 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009039 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309040 pthread_mutex_unlock(&adev->lock);
9041
Naresh Tannirud7205b62014-06-20 02:54:48 +05309042exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009043 str = str_parms_to_str(reply);
9044 str_parms_destroy(query);
9045 str_parms_destroy(reply);
9046
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309047 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009048 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009049}
9050
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009051static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009052{
9053 return 0;
9054}
9055
9056static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9057{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009058 int ret;
9059 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009060
9061 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9062
Haynes Mathew George5191a852013-09-11 14:19:36 -07009063 pthread_mutex_lock(&adev->lock);
9064 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009065 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009066 pthread_mutex_unlock(&adev->lock);
9067 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009068}
9069
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009070static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9071 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009072{
9073 return -ENOSYS;
9074}
9075
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009076static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9077 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009078{
9079 return -ENOSYS;
9080}
9081
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009082static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9083 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009084{
9085 return -ENOSYS;
9086}
9087
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009088static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9089 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009090{
9091 return -ENOSYS;
9092}
9093
9094static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9095{
9096 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009097 struct listnode *node;
9098 struct audio_usecase *usecase = NULL;
9099 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009101 pthread_mutex_lock(&adev->lock);
9102 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309103 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9104 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009105 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309106 if( mode == AUDIO_MODE_CALL_SCREEN ){
9107 adev->current_call_output = adev->primary_output;
9108 voice_start_call(adev);
9109 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009110 (mode == AUDIO_MODE_NORMAL ||
9111 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009112 list_for_each(node, &adev->usecase_list) {
9113 usecase = node_to_item(node, struct audio_usecase, list);
9114 if (usecase->type == VOICE_CALL)
9115 break;
9116 }
9117 if (usecase &&
9118 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9119 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9120 true);
9121 if (ret != 0) {
9122 /* default service interval was successfully updated,
9123 reopen USB backend with new service interval */
9124 check_usecases_codec_backend(adev,
9125 usecase,
9126 usecase->out_snd_device);
9127 }
9128 }
9129
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009130 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009131 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009132 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009133 // restore device for other active usecases after stop call
9134 list_for_each(node, &adev->usecase_list) {
9135 usecase = node_to_item(node, struct audio_usecase, list);
9136 select_devices(adev, usecase->id);
9137 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009139 }
9140 pthread_mutex_unlock(&adev->lock);
9141 return 0;
9142}
9143
9144static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9145{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009146 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009147 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009148
9149 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009150 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009151 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009152
Derek Chend2530072014-11-24 12:39:14 -08009153 if (adev->ext_hw_plugin)
9154 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009155
9156 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009157 pthread_mutex_unlock(&adev->lock);
9158
9159 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009160}
9161
9162static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9163{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009164 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009165 return 0;
9166}
9167
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009168static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009169 const struct audio_config *config)
9170{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009171 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172
Aalique Grahame22e49102018-12-18 14:23:57 -08009173 /* Don't know if USB HIFI in this context so use true to be conservative */
9174 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9175 true /*is_usb_hifi */) != 0)
9176 return 0;
9177
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009178 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9179 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009180}
9181
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009182static bool adev_input_allow_hifi_record(struct audio_device *adev,
9183 audio_devices_t devices,
9184 audio_input_flags_t flags,
9185 audio_source_t source) {
9186 const bool allowed = true;
9187
9188 if (!audio_is_usb_in_device(devices))
9189 return !allowed;
9190
9191 switch (flags) {
9192 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009193 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009194 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9195 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009196 default:
9197 return !allowed;
9198 }
9199
9200 switch (source) {
9201 case AUDIO_SOURCE_DEFAULT:
9202 case AUDIO_SOURCE_MIC:
9203 case AUDIO_SOURCE_UNPROCESSED:
9204 break;
9205 default:
9206 return !allowed;
9207 }
9208
9209 switch (adev->mode) {
9210 case 0:
9211 break;
9212 default:
9213 return !allowed;
9214 }
9215
9216 return allowed;
9217}
9218
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009219static int adev_update_voice_comm_input_stream(struct stream_in *in,
9220 struct audio_config *config)
9221{
9222 bool valid_rate = (config->sample_rate == 8000 ||
9223 config->sample_rate == 16000 ||
9224 config->sample_rate == 32000 ||
9225 config->sample_rate == 48000);
9226 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9227
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009228 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009229 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009230 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9231 in->config = default_pcm_config_voip_copp;
9232 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9233 DEFAULT_VOIP_BUF_DURATION_MS,
9234 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009235 } else {
9236 ALOGW("%s No valid input in voip, use defaults"
9237 "sample rate %u, channel mask 0x%X",
9238 __func__, config->sample_rate, in->channel_mask);
9239 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009240 in->config.rate = config->sample_rate;
9241 in->sample_rate = config->sample_rate;
9242 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009243 //XXX needed for voice_extn_compress_voip_open_input_stream
9244 in->config.rate = config->sample_rate;
9245 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309246 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009247 voice_extn_compress_voip_is_active(in->dev)) &&
9248 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9249 valid_rate && valid_ch) {
9250 voice_extn_compress_voip_open_input_stream(in);
9251 // update rate entries to match config from AF
9252 in->config.rate = config->sample_rate;
9253 in->sample_rate = config->sample_rate;
9254 } else {
9255 ALOGW("%s compress voip not active, use defaults", __func__);
9256 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009257 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009258 return 0;
9259}
9260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009261static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009262 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009263 audio_devices_t devices,
9264 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009265 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309266 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009267 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009268 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009269{
9270 struct audio_device *adev = (struct audio_device *)dev;
9271 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009272 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009273 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009274 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309275 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009276 bool is_usb_dev = audio_is_usb_in_device(devices);
9277 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9278 devices,
9279 flags,
9280 source);
Andy Hung94320602018-10-29 18:31:12 -07009281 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9282 " sample_rate %u, channel_mask %#x, format %#x",
9283 __func__, flags, is_usb_dev, may_use_hifi_record,
9284 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309285
kunleizdff872d2018-08-20 14:40:33 +08009286 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009287 is_usb_dev = false;
9288 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9289 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9290 __func__, devices);
9291 }
9292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009293 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009294
9295 if (!(is_usb_dev && may_use_hifi_record)) {
9296 if (config->sample_rate == 0)
9297 config->sample_rate = 48000;
9298 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9299 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9300 if (config->format == AUDIO_FORMAT_DEFAULT)
9301 config->format = AUDIO_FORMAT_PCM_16_BIT;
9302
9303 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9304
Aalique Grahame22e49102018-12-18 14:23:57 -08009305 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9306 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009307 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009309
Rahul Sharma99770982019-03-06 17:05:26 +05309310 pthread_mutex_lock(&adev->lock);
9311 if (in_get_stream(adev, handle) != NULL) {
9312 ALOGW("%s, input stream already opened", __func__);
9313 ret = -EEXIST;
9314 }
9315 pthread_mutex_unlock(&adev->lock);
9316 if (ret)
9317 return ret;
9318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009319 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009320
9321 if (!in) {
9322 ALOGE("failed to allocate input stream");
9323 return -ENOMEM;
9324 }
9325
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309326 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309327 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9328 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009329 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009330 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009332 in->stream.common.get_sample_rate = in_get_sample_rate;
9333 in->stream.common.set_sample_rate = in_set_sample_rate;
9334 in->stream.common.get_buffer_size = in_get_buffer_size;
9335 in->stream.common.get_channels = in_get_channels;
9336 in->stream.common.get_format = in_get_format;
9337 in->stream.common.set_format = in_set_format;
9338 in->stream.common.standby = in_standby;
9339 in->stream.common.dump = in_dump;
9340 in->stream.common.set_parameters = in_set_parameters;
9341 in->stream.common.get_parameters = in_get_parameters;
9342 in->stream.common.add_audio_effect = in_add_audio_effect;
9343 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9344 in->stream.set_gain = in_set_gain;
9345 in->stream.read = in_read;
9346 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009347 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309348 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009349 in->stream.set_microphone_direction = in_set_microphone_direction;
9350 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009351 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009352
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009353 list_init(&in->device_list);
9354 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009355 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009356 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009357 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009358 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009359 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009360 in->bit_width = 16;
9361 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009362 in->direction = MIC_DIRECTION_UNSPECIFIED;
9363 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009364 list_init(&in->aec_list);
9365 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009366 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009367
Andy Hung94320602018-10-29 18:31:12 -07009368 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009369 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9370 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9371 /* Force channel config requested to mono if incall
9372 record is being requested for only uplink/downlink */
9373 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9374 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9375 ret = -EINVAL;
9376 goto err_open;
9377 }
9378 }
9379
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009380 if (is_usb_dev && may_use_hifi_record) {
9381 /* HiFi record selects an appropriate format, channel, rate combo
9382 depending on sink capabilities*/
9383 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9384 &config->format,
9385 &in->supported_formats[0],
9386 MAX_SUPPORTED_FORMATS,
9387 &config->channel_mask,
9388 &in->supported_channel_masks[0],
9389 MAX_SUPPORTED_CHANNEL_MASKS,
9390 &config->sample_rate,
9391 &in->supported_sample_rates[0],
9392 MAX_SUPPORTED_SAMPLE_RATES);
9393 if (ret != 0) {
9394 ret = -EINVAL;
9395 goto err_open;
9396 }
9397 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009398 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309399 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309400 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9401 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9402 in->config.format = PCM_FORMAT_S32_LE;
9403 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309404 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9405 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9406 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9407 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9408 bool ret_error = false;
9409 in->bit_width = 24;
9410 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9411 from HAL is 24_packed and 8_24
9412 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9413 24_packed return error indicating supported format is 24_packed
9414 *> In case of any other source requesting 24 bit or float return error
9415 indicating format supported is 16 bit only.
9416
9417 on error flinger will retry with supported format passed
9418 */
9419 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9420 (source != AUDIO_SOURCE_CAMCORDER)) {
9421 config->format = AUDIO_FORMAT_PCM_16_BIT;
9422 if (config->sample_rate > 48000)
9423 config->sample_rate = 48000;
9424 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009425 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9426 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309427 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9428 ret_error = true;
9429 }
9430
9431 if (ret_error) {
9432 ret = -EINVAL;
9433 goto err_open;
9434 }
9435 }
9436
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009437 in->channel_mask = config->channel_mask;
9438 in->format = config->format;
9439
9440 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309441
9442 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9443 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9444 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9445 else {
9446 ret = -EINVAL;
9447 goto err_open;
9448 }
9449 }
9450
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009451 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309452 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9453 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009454 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9455 is_low_latency = true;
9456#if LOW_LATENCY_CAPTURE_USE_CASE
9457 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9458#endif
9459 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009460 if (!in->realtime) {
9461 in->config = pcm_config_audio_capture;
9462 frame_size = audio_stream_in_frame_size(&in->stream);
9463 buffer_size = get_input_buffer_size(config->sample_rate,
9464 config->format,
9465 channel_count,
9466 is_low_latency);
9467 in->config.period_size = buffer_size / frame_size;
9468 in->config.rate = config->sample_rate;
9469 in->af_period_multiplier = 1;
9470 } else {
9471 // period size is left untouched for rt mode playback
9472 in->config = pcm_config_audio_capture_rt;
9473 in->af_period_multiplier = af_period_multiplier;
9474 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009475 }
9476
9477 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9478 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9479 in->realtime = 0;
9480 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9481 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009482 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009483 in->stream.start = in_start;
9484 in->stream.stop = in_stop;
9485 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9486 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009487 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009488 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009489 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9490 in->config = pcm_config_audio_capture;
9491 frame_size = audio_stream_in_frame_size(&in->stream);
9492 buffer_size = get_input_buffer_size(config->sample_rate,
9493 config->format,
9494 channel_count,
9495 false /*is_low_latency*/);
9496 in->config.period_size = buffer_size / frame_size;
9497 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009498 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009499 switch (config->format) {
9500 case AUDIO_FORMAT_PCM_32_BIT:
9501 in->bit_width = 32;
9502 break;
9503 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9504 case AUDIO_FORMAT_PCM_8_24_BIT:
9505 in->bit_width = 24;
9506 break;
9507 default:
9508 in->bit_width = 16;
9509 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009510 } else if (is_single_device_type_equal(&in->device_list,
9511 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9512 is_single_device_type_equal(&in->device_list,
9513 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009514 if (config->sample_rate == 0)
9515 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9516 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9517 config->sample_rate != 8000) {
9518 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9519 ret = -EINVAL;
9520 goto err_open;
9521 }
9522 if (config->format == AUDIO_FORMAT_DEFAULT)
9523 config->format = AUDIO_FORMAT_PCM_16_BIT;
9524 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9525 config->format = AUDIO_FORMAT_PCM_16_BIT;
9526 ret = -EINVAL;
9527 goto err_open;
9528 }
9529
9530 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009531 if (adev->ha_proxy_enable &&
9532 is_single_device_type_equal(&in->device_list,
9533 AUDIO_DEVICE_IN_TELEPHONY_RX))
9534 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009535 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009536 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009537 in->af_period_multiplier = 1;
9538 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9539 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9540 (config->sample_rate == 8000 ||
9541 config->sample_rate == 16000 ||
9542 config->sample_rate == 32000 ||
9543 config->sample_rate == 48000) &&
9544 channel_count == 1) {
9545 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9546 in->config = pcm_config_audio_capture;
9547 frame_size = audio_stream_in_frame_size(&in->stream);
9548 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9549 config->sample_rate,
9550 config->format,
9551 channel_count, false /*is_low_latency*/);
9552 in->config.period_size = buffer_size / frame_size;
9553 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9554 in->config.rate = config->sample_rate;
9555 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009556 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309557 int ret_val;
9558 pthread_mutex_lock(&adev->lock);
9559 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9560 in, config, &channel_mask_updated);
9561 pthread_mutex_unlock(&adev->lock);
9562
9563 if (!ret_val) {
9564 if (channel_mask_updated == true) {
9565 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9566 __func__, config->channel_mask);
9567 ret = -EINVAL;
9568 goto err_open;
9569 }
9570 ALOGD("%s: created multi-channel session succesfully",__func__);
9571 } else if (audio_extn_compr_cap_enabled() &&
9572 audio_extn_compr_cap_format_supported(config->format) &&
9573 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9574 audio_extn_compr_cap_init(in);
9575 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309576 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309577 if (ret)
9578 goto err_open;
9579 } else {
9580 in->config = pcm_config_audio_capture;
9581 in->config.rate = config->sample_rate;
9582 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309583 in->format = config->format;
9584 frame_size = audio_stream_in_frame_size(&in->stream);
9585 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009586 config->format,
9587 channel_count,
9588 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009589 /* prevent division-by-zero */
9590 if (frame_size == 0) {
9591 ALOGE("%s: Error frame_size==0", __func__);
9592 ret = -EINVAL;
9593 goto err_open;
9594 }
9595
Revathi Uddarajud2634032017-12-07 14:42:34 +05309596 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009597 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009598
Revathi Uddarajud2634032017-12-07 14:42:34 +05309599 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9600 /* optionally use VOIP usecase depending on config(s) */
9601 ret = adev_update_voice_comm_input_stream(in, config);
9602 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009603
Revathi Uddarajud2634032017-12-07 14:42:34 +05309604 if (ret) {
9605 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9606 goto err_open;
9607 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009608 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309609
9610 /* assign concurrent capture usecase if record has to caried out from
9611 * actual hardware input source */
9612 if (audio_extn_is_concurrent_capture_enabled() &&
9613 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309614 /* Acquire lock to avoid two concurrent use cases initialized to
9615 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009616
Samyak Jainc37062f2019-04-25 18:41:06 +05309617 if (in->usecase == USECASE_AUDIO_RECORD) {
9618 pthread_mutex_lock(&adev->lock);
9619 if (!(adev->pcm_record_uc_state)) {
9620 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9621 adev->pcm_record_uc_state = 1;
9622 pthread_mutex_unlock(&adev->lock);
9623 } else {
9624 pthread_mutex_unlock(&adev->lock);
9625 /* Assign compress record use case for second record */
9626 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9627 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9628 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9629 if (audio_extn_cin_applicable_stream(in)) {
9630 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309631 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309632 if (ret)
9633 goto err_open;
9634 }
9635 }
9636 }
kunleiz28c73e72019-03-27 17:24:04 +08009637 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009638 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309639 if (audio_extn_ssr_get_stream() != in)
9640 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009641
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009642 in->sample_rate = in->config.rate;
9643
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309644 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9645 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009646 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009647 in->sample_rate, in->bit_width,
9648 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309649 register_format(in->format, in->supported_formats);
9650 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9651 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309652
Aalique Grahame22e49102018-12-18 14:23:57 -08009653 in->error_log = error_log_create(
9654 ERROR_LOG_ENTRIES,
9655 1000000000 /* aggregate consecutive identical errors within one second */);
9656
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009657 /* This stream could be for sound trigger lab,
9658 get sound trigger pcm if present */
9659 audio_extn_sound_trigger_check_and_get_session(in);
9660
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309661 lock_input_stream(in);
9662 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9663 pthread_mutex_lock(&adev->lock);
9664 in->card_status = adev->card_status;
9665 pthread_mutex_unlock(&adev->lock);
9666 pthread_mutex_unlock(&in->lock);
9667
Aalique Grahame22e49102018-12-18 14:23:57 -08009668 stream_app_type_cfg_init(&in->app_type_cfg);
9669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009670 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009671
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009672 ret = io_streams_map_insert(adev, &in->stream.common,
9673 handle, AUDIO_PATCH_HANDLE_NONE);
9674 if (ret != 0)
9675 goto err_open;
9676
Derek Chenf939fb72018-11-13 13:34:41 -08009677 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9678 calloc(1, sizeof(streams_input_ctxt_t));
9679 if (in_ctxt == NULL) {
9680 ALOGE("%s fail to allocate input ctxt", __func__);
9681 ret = -ENOMEM;
9682 goto err_open;
9683 }
9684 in_ctxt->input = in;
9685
9686 pthread_mutex_lock(&adev->lock);
9687 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9688 pthread_mutex_unlock(&adev->lock);
9689
Eric Laurent994a6932013-07-17 11:51:42 -07009690 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009692
9693err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309694 if (in->usecase == USECASE_AUDIO_RECORD) {
9695 pthread_mutex_lock(&adev->lock);
9696 adev->pcm_record_uc_state = 0;
9697 pthread_mutex_unlock(&adev->lock);
9698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009699 free(in);
9700 *stream_in = NULL;
9701 return ret;
9702}
9703
9704static void adev_close_input_stream(struct audio_hw_device *dev,
9705 struct audio_stream_in *stream)
9706{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009707 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009708 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009709 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309710
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309711 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009712
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009713 if (in == NULL) {
9714 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9715 return;
9716 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009717 io_streams_map_remove(adev, in->capture_handle);
9718
kunleiz70e57612018-12-28 17:50:23 +08009719 /* must deregister from sndmonitor first to prevent races
9720 * between the callback and close_stream
9721 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309722 audio_extn_snd_mon_unregister_listener(stream);
9723
kunleiz70e57612018-12-28 17:50:23 +08009724 /* Disable echo reference if there are no active input, hfp call
9725 * and sound trigger while closing input stream
9726 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009727 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009728 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009729 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9730 struct listnode out_devices;
9731 list_init(&out_devices);
9732 platform_set_echo_reference(adev, false, &out_devices);
9733 } else
kunleiz70e57612018-12-28 17:50:23 +08009734 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309735
Weiyin Jiang2995f662019-04-17 14:25:12 +08009736 error_log_destroy(in->error_log);
9737 in->error_log = NULL;
9738
Pallavid7c7a272018-01-16 11:22:55 +05309739
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009740 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309741 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009742 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309743 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009744 if (ret != 0)
9745 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9746 __func__, ret);
9747 } else
9748 in_standby(&stream->common);
9749
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009750 pthread_mutex_destroy(&in->lock);
9751 pthread_mutex_destroy(&in->pre_lock);
9752
Revathi Uddarajud2634032017-12-07 14:42:34 +05309753 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309754 if (in->usecase == USECASE_AUDIO_RECORD) {
9755 adev->pcm_record_uc_state = 0;
9756 }
9757
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009758 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9759 adev->enable_voicerx = false;
9760 }
9761
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009762 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009763 audio_extn_ssr_deinit();
9764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009765
Garmond Leunge2433c32017-09-28 21:51:22 -07009766 if (audio_extn_ffv_get_stream() == in) {
9767 audio_extn_ffv_stream_deinit();
9768 }
9769
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309770 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009771 audio_extn_compr_cap_format_supported(in->config.format))
9772 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309773
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309774 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309775 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009776
Mingming Yinfd7607b2016-01-22 12:48:44 -08009777 if (in->is_st_session) {
9778 ALOGV("%s: sound trigger pcm stop lab", __func__);
9779 audio_extn_sound_trigger_stop_lab(in);
9780 }
Derek Chenf939fb72018-11-13 13:34:41 -08009781 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9782 if (in_ctxt != NULL) {
9783 list_remove(&in_ctxt->list);
9784 free(in_ctxt);
9785 } else {
9786 ALOGW("%s, input stream already closed", __func__);
9787 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009788 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309789 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009790 return;
9791}
9792
Aalique Grahame22e49102018-12-18 14:23:57 -08009793/* verifies input and output devices and their capabilities.
9794 *
9795 * This verification is required when enabling extended bit-depth or
9796 * sampling rates, as not all qcom products support it.
9797 *
9798 * Suitable for calling only on initialization such as adev_open().
9799 * It fills the audio_device use_case_table[] array.
9800 *
9801 * Has a side-effect that it needs to configure audio routing / devices
9802 * in order to power up the devices and read the device parameters.
9803 * It does not acquire any hw device lock. Should restore the devices
9804 * back to "normal state" upon completion.
9805 */
9806static int adev_verify_devices(struct audio_device *adev)
9807{
9808 /* enumeration is a bit difficult because one really wants to pull
9809 * the use_case, device id, etc from the hidden pcm_device_table[].
9810 * In this case there are the following use cases and device ids.
9811 *
9812 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9813 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9814 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9815 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9816 * [USECASE_AUDIO_RECORD] = {0, 0},
9817 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9818 * [USECASE_VOICE_CALL] = {2, 2},
9819 *
9820 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9821 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9822 */
9823
9824 /* should be the usecases enabled in adev_open_input_stream() */
9825 static const int test_in_usecases[] = {
9826 USECASE_AUDIO_RECORD,
9827 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9828 };
9829 /* should be the usecases enabled in adev_open_output_stream()*/
9830 static const int test_out_usecases[] = {
9831 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9832 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9833 };
9834 static const usecase_type_t usecase_type_by_dir[] = {
9835 PCM_PLAYBACK,
9836 PCM_CAPTURE,
9837 };
9838 static const unsigned flags_by_dir[] = {
9839 PCM_OUT,
9840 PCM_IN,
9841 };
9842
9843 size_t i;
9844 unsigned dir;
9845 const unsigned card_id = adev->snd_card;
9846
9847 for (dir = 0; dir < 2; ++dir) {
9848 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9849 const unsigned flags_dir = flags_by_dir[dir];
9850 const size_t testsize =
9851 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9852 const int *testcases =
9853 dir ? test_in_usecases : test_out_usecases;
9854 const audio_devices_t audio_device =
9855 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9856
9857 for (i = 0; i < testsize; ++i) {
9858 const audio_usecase_t audio_usecase = testcases[i];
9859 int device_id;
9860 struct pcm_params **pparams;
9861 struct stream_out out;
9862 struct stream_in in;
9863 struct audio_usecase uc_info;
9864 int retval;
9865
9866 pparams = &adev->use_case_table[audio_usecase];
9867 pcm_params_free(*pparams); /* can accept null input */
9868 *pparams = NULL;
9869
9870 /* find the device ID for the use case (signed, for error) */
9871 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9872 if (device_id < 0)
9873 continue;
9874
9875 /* prepare structures for device probing */
9876 memset(&uc_info, 0, sizeof(uc_info));
9877 uc_info.id = audio_usecase;
9878 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009879 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009880 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009881 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009882 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009883 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009884 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9885 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009886 }
9887 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009888 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009889 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009890 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009891 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009892 uc_info.in_snd_device = SND_DEVICE_NONE;
9893 uc_info.out_snd_device = SND_DEVICE_NONE;
9894 list_add_tail(&adev->usecase_list, &uc_info.list);
9895
9896 /* select device - similar to start_(in/out)put_stream() */
9897 retval = select_devices(adev, audio_usecase);
9898 if (retval >= 0) {
9899 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9900#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009901 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009902 if (*pparams) {
9903 ALOGV("%s: (%s) card %d device %d", __func__,
9904 dir ? "input" : "output", card_id, device_id);
9905 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9906 } else {
9907 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9908 }
9909#endif
9910 }
9911
9912 /* deselect device - similar to stop_(in/out)put_stream() */
9913 /* 1. Get and set stream specific mixer controls */
9914 retval = disable_audio_route(adev, &uc_info);
9915 /* 2. Disable the rx device */
9916 retval = disable_snd_device(adev,
9917 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9918 list_remove(&uc_info.list);
9919 }
9920 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009921 return 0;
9922}
9923
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009924int update_patch(unsigned int num_sources,
9925 const struct audio_port_config *sources,
9926 unsigned int num_sinks,
9927 const struct audio_port_config *sinks,
9928 audio_patch_handle_t handle,
9929 struct audio_patch_info *p_info,
9930 patch_type_t patch_type, bool new_patch)
9931{
9932 ALOGD("%s: enter", __func__);
9933
9934 if (p_info == NULL) {
9935 ALOGE("%s: Invalid patch pointer", __func__);
9936 return -EINVAL;
9937 }
9938
9939 if (new_patch) {
9940 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9941 if (p_info->patch == NULL) {
9942 ALOGE("%s: Could not allocate patch", __func__);
9943 return -ENOMEM;
9944 }
9945 }
9946
9947 p_info->patch->id = handle;
9948 p_info->patch->num_sources = num_sources;
9949 p_info->patch->num_sinks = num_sinks;
9950
9951 for (int i = 0; i < num_sources; i++)
9952 p_info->patch->sources[i] = sources[i];
9953 for (int i = 0; i < num_sinks; i++)
9954 p_info->patch->sinks[i] = sinks[i];
9955
9956 p_info->patch_type = patch_type;
9957 return 0;
9958}
9959
9960audio_patch_handle_t generate_patch_handle()
9961{
9962 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9963 if (++patch_handle < 0)
9964 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9965 return patch_handle;
9966}
9967
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309968int adev_create_audio_patch(struct audio_hw_device *dev,
9969 unsigned int num_sources,
9970 const struct audio_port_config *sources,
9971 unsigned int num_sinks,
9972 const struct audio_port_config *sinks,
9973 audio_patch_handle_t *handle)
9974{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009975 int ret = 0;
9976 struct audio_device *adev = (struct audio_device *)dev;
9977 struct audio_patch_info *p_info = NULL;
9978 patch_type_t patch_type = PATCH_NONE;
9979 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9980 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9981 struct audio_stream_info *s_info = NULL;
9982 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009983 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009984 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9985 bool new_patch = false;
9986 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309987
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009988 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9989 num_sources, num_sinks, *handle);
9990
9991 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9992 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9993 ALOGE("%s: Invalid patch arguments", __func__);
9994 ret = -EINVAL;
9995 goto done;
9996 }
9997
9998 if (num_sources > 1) {
9999 ALOGE("%s: Multiple sources are not supported", __func__);
10000 ret = -EINVAL;
10001 goto done;
10002 }
10003
10004 if (sources == NULL || sinks == NULL) {
10005 ALOGE("%s: Invalid sources or sinks port config", __func__);
10006 ret = -EINVAL;
10007 goto done;
10008 }
10009
10010 ALOGV("%s: source role %d, source type %d", __func__,
10011 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010012 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010013
10014 // Populate source/sink information and fetch stream info
10015 switch (sources[0].type) {
10016 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10017 device_type = sources[0].ext.device.type;
10018 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010019 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010020 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10021 patch_type = PATCH_CAPTURE;
10022 io_handle = sinks[0].ext.mix.handle;
10023 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010024 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025 __func__, device_type, io_handle);
10026 } else {
10027 // Device to device patch is not implemented.
10028 // This space will need changes if audio HAL
10029 // handles device to device patches in the future.
10030 patch_type = PATCH_DEVICE_LOOPBACK;
10031 }
10032 break;
10033 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10034 io_handle = sources[0].ext.mix.handle;
10035 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010036 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010038 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010039 }
10040 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010041 ALOGD("%s: Playback patch from mix handle %d to device %x",
10042 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010043 break;
10044 case AUDIO_PORT_TYPE_SESSION:
10045 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010046 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10047 ret = -EINVAL;
10048 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 }
10050
10051 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010052
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010053 // Generate patch info and update patch
10054 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010055 *handle = generate_patch_handle();
10056 p_info = (struct audio_patch_info *)
10057 calloc(1, sizeof(struct audio_patch_info));
10058 if (p_info == NULL) {
10059 ALOGE("%s: Failed to allocate memory", __func__);
10060 pthread_mutex_unlock(&adev->lock);
10061 ret = -ENOMEM;
10062 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010063 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010064 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010065 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010066 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010067 if (p_info == NULL) {
10068 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10069 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010070 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010071 ret = -EINVAL;
10072 goto done;
10073 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010074 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010076 *handle, p_info, patch_type, new_patch);
10077
10078 // Fetch stream info of associated mix for playback or capture patches
10079 if (p_info->patch_type == PATCH_PLAYBACK ||
10080 p_info->patch_type == PATCH_CAPTURE) {
10081 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10082 if (s_info == NULL) {
10083 ALOGE("%s: Failed to obtain stream info", __func__);
10084 if (new_patch)
10085 free(p_info);
10086 pthread_mutex_unlock(&adev->lock);
10087 ret = -EINVAL;
10088 goto done;
10089 }
10090 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10091 s_info->patch_handle = *handle;
10092 stream = s_info->stream;
10093 }
10094 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095
10096 // Update routing for stream
10097 if (stream != NULL) {
10098 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010099 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010101 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010102 if (ret < 0) {
10103 pthread_mutex_lock(&adev->lock);
10104 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10105 if (new_patch)
10106 free(p_info);
10107 pthread_mutex_unlock(&adev->lock);
10108 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10109 goto done;
10110 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010111 }
10112
10113 // Add new patch to patch map
10114 if (!ret && new_patch) {
10115 pthread_mutex_lock(&adev->lock);
10116 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010117 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010118 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010119 }
10120
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010121done:
10122 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010123 num_sources,
10124 sources,
10125 num_sinks,
10126 sinks,
10127 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010129 num_sources,
10130 sources,
10131 num_sinks,
10132 sinks,
10133 handle);
10134 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010135}
10136
10137int adev_release_audio_patch(struct audio_hw_device *dev,
10138 audio_patch_handle_t handle)
10139{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 struct audio_device *adev = (struct audio_device *) dev;
10141 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010142 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010143 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010144
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010145 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10146 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10147 ret = -EINVAL;
10148 goto done;
10149 }
10150
10151 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010152 pthread_mutex_lock(&adev->lock);
10153 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010154 if (p_info == NULL) {
10155 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010156 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010157 ret = -EINVAL;
10158 goto done;
10159 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010160 struct audio_patch *patch = p_info->patch;
10161 if (patch == NULL) {
10162 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010163 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010164 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 goto done;
10166 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010167 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10168 switch (patch->sources[0].type) {
10169 case AUDIO_PORT_TYPE_MIX:
10170 io_handle = patch->sources[0].ext.mix.handle;
10171 break;
10172 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010173 if (p_info->patch_type == PATCH_CAPTURE)
10174 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 break;
10176 case AUDIO_PORT_TYPE_SESSION:
10177 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010178 pthread_mutex_unlock(&adev->lock);
10179 ret = -EINVAL;
10180 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010181 }
10182
10183 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010184 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010185 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010186 if (patch_type == PATCH_PLAYBACK ||
10187 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010188 struct audio_stream_info *s_info =
10189 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10190 if (s_info == NULL) {
10191 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10192 pthread_mutex_unlock(&adev->lock);
10193 goto done;
10194 }
10195 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10196 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010197 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010198 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010199
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010200 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010201 struct listnode devices;
10202 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010203 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010204 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010205 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010206 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010207 }
10208
10209 if (ret < 0)
10210 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10211
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212done:
10213 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10214 audio_extn_auto_hal_release_audio_patch(dev, handle);
10215
10216 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010217 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010218}
10219
10220int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10221{
Derek Chenf13dd492018-11-13 14:53:51 -080010222 int ret = 0;
10223
10224 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10225 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10226 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010227}
10228
10229int adev_set_audio_port_config(struct audio_hw_device *dev,
10230 const struct audio_port_config *config)
10231{
Derek Chenf13dd492018-11-13 14:53:51 -080010232 int ret = 0;
10233
10234 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10235 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10236 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010237}
10238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010239static int adev_dump(const audio_hw_device_t *device __unused,
10240 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010241{
10242 return 0;
10243}
10244
10245static int adev_close(hw_device_t *device)
10246{
Aalique Grahame22e49102018-12-18 14:23:57 -080010247 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010248 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010249
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010250 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010251 return 0;
10252
10253 pthread_mutex_lock(&adev_init_lock);
10254
10255 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010256 if (audio_extn_spkr_prot_is_enabled())
10257 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010258 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010259 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010260 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010261 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010262 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010263 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010264 audio_extn_utils_release_streams_cfg_lists(
10265 &adev->streams_output_cfg_list,
10266 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010267 if (audio_extn_qap_is_enabled())
10268 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010269 if (audio_extn_qaf_is_enabled())
10270 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010271 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010272 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010273 free(adev->snd_dev_ref_cnt);
10274 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010275 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10276 pcm_params_free(adev->use_case_table[i]);
10277 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010278 if (adev->adm_deinit)
10279 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010280 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010281 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010282 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010283 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010284 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010285 if (adev->device_cfg_params) {
10286 free(adev->device_cfg_params);
10287 adev->device_cfg_params = NULL;
10288 }
Derek Chend2530072014-11-24 12:39:14 -080010289 if(adev->ext_hw_plugin)
10290 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010291 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010292 free_map(adev->patch_map);
10293 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010294 free(device);
10295 adev = NULL;
10296 }
10297 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010298 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010299 return 0;
10300}
10301
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010302/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10303 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10304 * just that it _might_ work.
10305 */
10306static int period_size_is_plausible_for_low_latency(int period_size)
10307{
10308 switch (period_size) {
10309 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010310 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010311 case 240:
10312 case 320:
10313 case 480:
10314 return 1;
10315 default:
10316 return 0;
10317 }
10318}
10319
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010320static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10321{
10322 bool is_snd_card_status = false;
10323 bool is_ext_device_status = false;
10324 char value[32];
10325 int card = -1;
10326 card_status_t status;
10327
10328 if (cookie != adev || !parms)
10329 return;
10330
10331 if (!parse_snd_card_status(parms, &card, &status)) {
10332 is_snd_card_status = true;
10333 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10334 is_ext_device_status = true;
10335 } else {
10336 // not a valid event
10337 return;
10338 }
10339
10340 pthread_mutex_lock(&adev->lock);
10341 if (card == adev->snd_card || is_ext_device_status) {
10342 if (is_snd_card_status && adev->card_status != status) {
10343 adev->card_status = status;
10344 platform_snd_card_update(adev->platform, status);
10345 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010346 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010347 if (status == CARD_STATUS_OFFLINE)
10348 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010349 } else if (is_ext_device_status) {
10350 platform_set_parameters(adev->platform, parms);
10351 }
10352 }
10353 pthread_mutex_unlock(&adev->lock);
10354 return;
10355}
10356
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010357/* adev lock held */
10358int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010359{
10360 struct audio_usecase *uc_info;
10361 float left_p;
10362 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010363 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010364
10365 uc_info = get_usecase_from_list(adev, out->usecase);
10366 if (uc_info == NULL) {
10367 ALOGE("%s: Could not find the usecase (%d) in the list",
10368 __func__, out->usecase);
10369 return -EINVAL;
10370 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010371 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010372
10373 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10374 out->usecase, use_case_table[out->usecase]);
10375
10376 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010377 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010378 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010379 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010380 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010381 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10382 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010383 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010384 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10385 if (out->a2dp_compress_mute) {
10386 out->a2dp_compress_mute = false;
10387 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10388 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010389 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010391 out->muted = false;
10392 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010393 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010394 pthread_mutex_lock(&out->latch_lock);
Zhou Songc576a452019-09-09 14:17:40 +080010395 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10396 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010397 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010398 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010399 assign_devices(&devices, &out->device_list);
10400 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010401 left_p = out->volume_l;
10402 right_p = out->volume_r;
10403 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10404 compress_pause(out->compr);
10405 out_set_compr_volume(&out->stream, (float)0, (float)0);
10406 out->a2dp_compress_mute = true;
10407 select_devices(adev, out->usecase);
10408 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10409 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010410 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010411 out->volume_l = left_p;
10412 out->volume_r = right_p;
10413 }
Zhou Songc576a452019-09-09 14:17:40 +080010414 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010415 // mute for non offloaded streams
10416 if (audio_extn_a2dp_source_is_suspended()) {
10417 out->muted = true;
10418 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010419 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010420 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010421 }
10422 ALOGV("%s: exit", __func__);
10423 return 0;
10424}
10425
Haynes Mathew George01156f92018-04-13 15:29:54 -070010426void adev_on_battery_status_changed(bool charging)
10427{
10428 pthread_mutex_lock(&adev->lock);
10429 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10430 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010431 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010432 pthread_mutex_unlock(&adev->lock);
10433}
10434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010435static int adev_open(const hw_module_t *module, const char *name,
10436 hw_device_t **device)
10437{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010438 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010439 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010440 char mixer_ctl_name[128] = {0};
10441 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010442
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010443 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010444 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10445
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010446 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010447 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010448 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010449 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010450 ALOGD("%s: returning existing instance of adev", __func__);
10451 ALOGD("%s: exit", __func__);
10452 pthread_mutex_unlock(&adev_init_lock);
10453 return 0;
10454 }
10455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010456 adev = calloc(1, sizeof(struct audio_device));
10457
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010458 if (!adev) {
10459 pthread_mutex_unlock(&adev_init_lock);
10460 return -ENOMEM;
10461 }
10462
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010463 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10464
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010465 // register audio ext hidl at the earliest
10466 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010467#ifdef DYNAMIC_LOG_ENABLED
10468 register_for_dynamic_logging("hal");
10469#endif
10470
Derek Chenf939fb72018-11-13 13:34:41 -080010471 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010472 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010473 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10474 maj_version = atoi(value);
10475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010476 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010477 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010478 adev->device.common.module = (struct hw_module_t *)module;
10479 adev->device.common.close = adev_close;
10480
10481 adev->device.init_check = adev_init_check;
10482 adev->device.set_voice_volume = adev_set_voice_volume;
10483 adev->device.set_master_volume = adev_set_master_volume;
10484 adev->device.get_master_volume = adev_get_master_volume;
10485 adev->device.set_master_mute = adev_set_master_mute;
10486 adev->device.get_master_mute = adev_get_master_mute;
10487 adev->device.set_mode = adev_set_mode;
10488 adev->device.set_mic_mute = adev_set_mic_mute;
10489 adev->device.get_mic_mute = adev_get_mic_mute;
10490 adev->device.set_parameters = adev_set_parameters;
10491 adev->device.get_parameters = adev_get_parameters;
10492 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10493 adev->device.open_output_stream = adev_open_output_stream;
10494 adev->device.close_output_stream = adev_close_output_stream;
10495 adev->device.open_input_stream = adev_open_input_stream;
10496 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010497 adev->device.create_audio_patch = adev_create_audio_patch;
10498 adev->device.release_audio_patch = adev_release_audio_patch;
10499 adev->device.get_audio_port = adev_get_audio_port;
10500 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010501 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010502 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010503
10504 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010505 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010506 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010507 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010508 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010509 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010510 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010511 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010512 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010513 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010514 /* Init audio and voice feature */
10515 audio_extn_feature_init();
10516 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010517 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010518 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010519 list_init(&adev->active_inputs_list);
10520 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010521 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010522 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10523 audio_extn_utils_hash_eq);
10524 if (!adev->io_streams_map) {
10525 ALOGE("%s: Could not create io streams map", __func__);
10526 ret = -ENOMEM;
10527 goto adev_open_err;
10528 }
10529 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10530 audio_extn_utils_hash_eq);
10531 if (!adev->patch_map) {
10532 ALOGE("%s: Could not create audio patch map", __func__);
10533 ret = -ENOMEM;
10534 goto adev_open_err;
10535 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010536 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010537 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010538 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010539 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010540 adev->perf_lock_opts[0] = 0x101;
10541 adev->perf_lock_opts[1] = 0x20E;
10542 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010543 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010544 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010545 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010546 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010547 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010548
Zhou Song68ebc352019-12-05 17:11:15 +080010549 audio_extn_perf_lock_init();
10550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010551 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010552 adev->platform = platform_init(adev);
10553 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010554 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010555 ret = -EINVAL;
10556 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010557 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010558
Aalique Grahame22e49102018-12-18 14:23:57 -080010559 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010560 if (audio_extn_qap_is_enabled()) {
10561 ret = audio_extn_qap_init(adev);
10562 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010563 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010564 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010565 }
10566 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10567 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10568 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010569
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010570 if (audio_extn_qaf_is_enabled()) {
10571 ret = audio_extn_qaf_init(adev);
10572 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010573 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010574 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010575 }
10576
10577 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10578 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10579 }
10580
Derek Chenae7b0342019-02-08 15:17:04 -080010581 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010582 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10583
Eric Laurentc4aef752013-09-12 17:45:53 -070010584 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10585 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10586 if (adev->visualizer_lib == NULL) {
10587 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10588 } else {
10589 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10590 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010591 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010592 "visualizer_hal_start_output");
10593 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010594 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010595 "visualizer_hal_stop_output");
10596 }
10597 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010598 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010599 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010600 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010601 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010602 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010603 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010604
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010605 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10606 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10607 if (adev->offload_effects_lib == NULL) {
10608 ALOGE("%s: DLOPEN failed for %s", __func__,
10609 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10610 } else {
10611 ALOGV("%s: DLOPEN successful for %s", __func__,
10612 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10613 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010614 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010615 "offload_effects_bundle_hal_start_output");
10616 adev->offload_effects_stop_output =
10617 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10618 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010619 adev->offload_effects_set_hpx_state =
10620 (int (*)(bool))dlsym(adev->offload_effects_lib,
10621 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010622 adev->offload_effects_get_parameters =
10623 (void (*)(struct str_parms *, struct str_parms *))
10624 dlsym(adev->offload_effects_lib,
10625 "offload_effects_bundle_get_parameters");
10626 adev->offload_effects_set_parameters =
10627 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10628 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010629 }
10630 }
10631
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010632 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10633 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10634 if (adev->adm_lib == NULL) {
10635 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10636 } else {
10637 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10638 adev->adm_init = (adm_init_t)
10639 dlsym(adev->adm_lib, "adm_init");
10640 adev->adm_deinit = (adm_deinit_t)
10641 dlsym(adev->adm_lib, "adm_deinit");
10642 adev->adm_register_input_stream = (adm_register_input_stream_t)
10643 dlsym(adev->adm_lib, "adm_register_input_stream");
10644 adev->adm_register_output_stream = (adm_register_output_stream_t)
10645 dlsym(adev->adm_lib, "adm_register_output_stream");
10646 adev->adm_deregister_stream = (adm_deregister_stream_t)
10647 dlsym(adev->adm_lib, "adm_deregister_stream");
10648 adev->adm_request_focus = (adm_request_focus_t)
10649 dlsym(adev->adm_lib, "adm_request_focus");
10650 adev->adm_abandon_focus = (adm_abandon_focus_t)
10651 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010652 adev->adm_set_config = (adm_set_config_t)
10653 dlsym(adev->adm_lib, "adm_set_config");
10654 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10655 dlsym(adev->adm_lib, "adm_request_focus_v2");
10656 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10657 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10658 adev->adm_on_routing_change = (adm_on_routing_change_t)
10659 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010660 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10661 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010662 }
10663 }
10664
Aalique Grahame22e49102018-12-18 14:23:57 -080010665 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010666 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010667 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010668 //initialize this to false for now,
10669 //this will be set to true through set param
10670 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010671
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010672 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010673 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010674
10675 if (k_enable_extended_precision)
10676 adev_verify_devices(adev);
10677
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010678 adev->dsp_bit_width_enforce_mode =
10679 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010680
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010681 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10682 &adev->streams_output_cfg_list,
10683 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010684
Kiran Kandi910e1862013-10-29 13:29:42 -070010685 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010686
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010687 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010688 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010689 trial = atoi(value);
10690 if (period_size_is_plausible_for_low_latency(trial)) {
10691 pcm_config_low_latency.period_size = trial;
10692 pcm_config_low_latency.start_threshold = trial / 4;
10693 pcm_config_low_latency.avail_min = trial / 4;
10694 configured_low_latency_capture_period_size = trial;
10695 }
10696 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010697 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10698 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010699 trial = atoi(value);
10700 if (period_size_is_plausible_for_low_latency(trial)) {
10701 configured_low_latency_capture_period_size = trial;
10702 }
10703 }
10704
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010705 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10706
Eric Laurent4b084132018-10-19 17:33:43 -070010707 adev->camera_orientation = CAMERA_DEFAULT;
10708
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010709 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010710 af_period_multiplier = atoi(value);
10711 if (af_period_multiplier < 0)
10712 af_period_multiplier = 2;
10713 else if (af_period_multiplier > 4)
10714 af_period_multiplier = 4;
10715
10716 ALOGV("new period_multiplier = %d", af_period_multiplier);
10717 }
10718
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010719 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010720
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010721 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010722 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010723 pthread_mutex_unlock(&adev_init_lock);
10724
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010725 if (adev->adm_init)
10726 adev->adm_data = adev->adm_init();
10727
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010728 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010729 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010730
10731 audio_extn_snd_mon_init();
10732 pthread_mutex_lock(&adev->lock);
10733 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10734 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010735 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10736 /*
10737 * if the battery state callback happens before charging can be queried,
10738 * it will be guarded with the adev->lock held in the cb function and so
10739 * the callback value will reflect the latest state
10740 */
10741 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010742 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010743 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010744 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010745 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010746 /* Allocate memory for Device config params */
10747 adev->device_cfg_params = (struct audio_device_config_param*)
10748 calloc(platform_get_max_codec_backend(),
10749 sizeof(struct audio_device_config_param));
10750 if (adev->device_cfg_params == NULL)
10751 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010752
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010753 /*
10754 * Check if new PSPD matrix mixer control is supported. If not
10755 * supported, then set flag so that old mixer ctrl is sent while
10756 * sending pspd coefficients on older kernel version. Query mixer
10757 * control for default pcm id and channel value one.
10758 */
10759 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10760 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10761
10762 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10763 if (!ctl) {
10764 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10765 __func__, mixer_ctl_name);
10766 adev->use_old_pspd_mix_ctrl = true;
10767 }
10768
Eric Laurent994a6932013-07-17 11:51:42 -070010769 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010770 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010771
10772adev_open_err:
10773 free_map(adev->patch_map);
10774 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010775 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010776 pthread_mutex_destroy(&adev->lock);
10777 free(adev);
10778 adev = NULL;
10779 *device = NULL;
10780 pthread_mutex_unlock(&adev_init_lock);
10781 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010782}
10783
10784static struct hw_module_methods_t hal_module_methods = {
10785 .open = adev_open,
10786};
10787
10788struct audio_module HAL_MODULE_INFO_SYM = {
10789 .common = {
10790 .tag = HARDWARE_MODULE_TAG,
10791 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10792 .hal_api_version = HARDWARE_HAL_API_VERSION,
10793 .id = AUDIO_HARDWARE_MODULE_ID,
10794 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010795 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010796 .methods = &hal_module_methods,
10797 },
10798};