blob: c5f3c7aa88e696312d85182bce03f9df429f7925 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530402 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500424 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400425
426 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
427 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
428 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800429 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700430};
431
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700432static const audio_usecase_t offload_usecases[] = {
433 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700434 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
436 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
441 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700442};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443
Varun Balaraje49253e2017-07-06 19:48:56 +0530444static const audio_usecase_t interactive_usecases[] = {
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
452 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
453};
454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455#define STRING_TO_ENUM(string) { #string, string }
456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457struct string_to_enum {
458 const char *name;
459 uint32_t value;
460};
461
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700462static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700471 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
472 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
473 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
481 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800482};
483
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700484static const struct string_to_enum formats_name_to_enum_table[] = {
485 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
486 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
487 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
489 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
490 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700491 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800492 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
493 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700494 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800495};
496
497//list of all supported sample rates by HDMI specification.
498static const int out_hdmi_sample_rates[] = {
499 32000, 44100, 48000, 88200, 96000, 176400, 192000,
500};
501
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700502static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800503 STRING_TO_ENUM(32000),
504 STRING_TO_ENUM(44100),
505 STRING_TO_ENUM(48000),
506 STRING_TO_ENUM(88200),
507 STRING_TO_ENUM(96000),
508 STRING_TO_ENUM(176400),
509 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800510 STRING_TO_ENUM(352800),
511 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700512};
513
Carter Hsu2e429db2019-05-14 18:50:52 +0800514struct in_effect_list {
515 struct listnode list;
516 effect_handle_t handle;
517};
518
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700519static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700520static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700521static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700522//cache last MBDRC cal step level
523static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700524
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530525static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700526static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800527static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530528static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530529
Derek Chen6f293672019-04-01 01:40:24 -0700530static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
531static void in_snd_mon_cb(void * stream, struct str_parms * parms);
532static void out_snd_mon_cb(void * stream, struct str_parms * parms);
533
Zhou Song331c8e52019-08-26 14:16:12 +0800534static int configure_btsco_sample_rate(snd_device_t snd_device);
535
Vatsal Buchac09ae062018-11-14 13:25:08 +0530536#ifdef AUDIO_FEATURE_ENABLED_GCOV
537extern void __gcov_flush();
538static void enable_gcov()
539{
540 __gcov_flush();
541}
542#else
543static void enable_gcov()
544{
545}
546#endif
547
justinweng20fb6d82019-02-21 18:49:00 -0700548static int in_set_microphone_direction(const struct audio_stream_in *stream,
549 audio_microphone_direction_t dir);
550static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
551
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700552static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
553 int flags __unused)
554{
555 int dir = 0;
556 switch (uc_id) {
557 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530558 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700559 dir = 1;
560 case USECASE_AUDIO_PLAYBACK_ULL:
561 break;
562 default:
563 return false;
564 }
565
566 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
567 PCM_PLAYBACK : PCM_CAPTURE);
568 if (adev->adm_is_noirq_avail)
569 return adev->adm_is_noirq_avail(adev->adm_data,
570 adev->snd_card, dev_id, dir);
571 return false;
572}
573
574static void register_out_stream(struct stream_out *out)
575{
576 struct audio_device *adev = out->dev;
577 if (is_offload_usecase(out->usecase) ||
578 !adev->adm_register_output_stream)
579 return;
580
581 // register stream first for backward compatibility
582 adev->adm_register_output_stream(adev->adm_data,
583 out->handle,
584 out->flags);
585
586 if (!adev->adm_set_config)
587 return;
588
589 if (out->realtime)
590 adev->adm_set_config(adev->adm_data,
591 out->handle,
592 out->pcm, &out->config);
593}
594
595static void register_in_stream(struct stream_in *in)
596{
597 struct audio_device *adev = in->dev;
598 if (!adev->adm_register_input_stream)
599 return;
600
601 adev->adm_register_input_stream(adev->adm_data,
602 in->capture_handle,
603 in->flags);
604
605 if (!adev->adm_set_config)
606 return;
607
608 if (in->realtime)
609 adev->adm_set_config(adev->adm_data,
610 in->capture_handle,
611 in->pcm,
612 &in->config);
613}
614
615static void request_out_focus(struct stream_out *out, long ns)
616{
617 struct audio_device *adev = out->dev;
618
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619 if (adev->adm_request_focus_v2)
620 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
621 else if (adev->adm_request_focus)
622 adev->adm_request_focus(adev->adm_data, out->handle);
623}
624
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700625static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626{
627 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700628 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700629
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700630 if (adev->adm_request_focus_v2_1)
631 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
632 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700633 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
634 else if (adev->adm_request_focus)
635 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700636
637 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700638}
639
640static void release_out_focus(struct stream_out *out)
641{
642 struct audio_device *adev = out->dev;
643
644 if (adev->adm_abandon_focus)
645 adev->adm_abandon_focus(adev->adm_data, out->handle);
646}
647
648static void release_in_focus(struct stream_in *in)
649{
650 struct audio_device *adev = in->dev;
651 if (adev->adm_abandon_focus)
652 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
653}
654
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530655static int parse_snd_card_status(struct str_parms *parms, int *card,
656 card_status_t *status)
657{
658 char value[32]={0};
659 char state[32]={0};
660
661 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
662 if (ret < 0)
663 return -1;
664
665 // sscanf should be okay as value is of max length 32.
666 // same as sizeof state.
667 if (sscanf(value, "%d,%s", card, state) < 2)
668 return -1;
669
670 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
671 CARD_STATUS_OFFLINE;
672 return 0;
673}
674
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700675static inline void adjust_frames_for_device_delay(struct stream_out *out,
676 uint32_t *dsp_frames) {
677 // Adjustment accounts for A2dp encoder latency with offload usecases
678 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800679 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700680 unsigned long offset =
681 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
682 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
683 }
684}
685
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700686static inline bool free_entry(void *key __unused,
687 void *value, void *context __unused)
688{
689 free(value);
690 return true;
691}
692
693static inline void free_map(Hashmap *map)
694{
695 if (map) {
696 hashmapForEach(map, free_entry, (void *) NULL);
697 hashmapFree(map);
698 }
699}
700
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800701static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700702 audio_patch_handle_t patch_handle)
703{
704 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
705 return;
706
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700707 struct audio_patch_info *p_info =
708 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
709 if (p_info) {
710 ALOGV("%s: Remove patch %d", __func__, patch_handle);
711 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
712 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700713 free(p_info);
714 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715}
716
717static inline int io_streams_map_insert(struct audio_device *adev,
718 struct audio_stream *stream,
719 audio_io_handle_t handle,
720 audio_patch_handle_t patch_handle)
721{
722 struct audio_stream_info *s_info =
723 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
724
725 if (s_info == NULL) {
726 ALOGE("%s: Could not allocate stream info", __func__);
727 return -ENOMEM;
728 }
729 s_info->stream = stream;
730 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700731
732 pthread_mutex_lock(&adev->lock);
733 struct audio_stream_info *stream_info =
734 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700735 if (stream_info != NULL)
736 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700738 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700739 return 0;
740}
741
742static inline void io_streams_map_remove(struct audio_device *adev,
743 audio_io_handle_t handle)
744{
745 pthread_mutex_lock(&adev->lock);
746 struct audio_stream_info *s_info =
747 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800749 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700750 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753done:
754 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700755 return;
756}
757
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800758static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700759 audio_patch_handle_t handle)
760{
761 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700762 p_info = (struct audio_patch_info *)
763 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700764 return p_info;
765}
766
vivek mehtaa76401a2015-04-24 14:12:15 -0700767__attribute__ ((visibility ("default")))
768bool audio_hw_send_gain_dep_calibration(int level) {
769 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700770 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700771
772 pthread_mutex_lock(&adev_init_lock);
773
774 if (adev != NULL && adev->platform != NULL) {
775 pthread_mutex_lock(&adev->lock);
776 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700777
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530778 // cache level info for any of the use case which
779 // was not started.
780 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700781
vivek mehtaa76401a2015-04-24 14:12:15 -0700782 pthread_mutex_unlock(&adev->lock);
783 } else {
784 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
785 }
786
787 pthread_mutex_unlock(&adev_init_lock);
788
789 return ret_val;
790}
791
Ashish Jain5106d362016-05-11 19:23:33 +0530792static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
793{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800794 bool gapless_enabled = false;
795 const char *mixer_ctl_name = "Compress Gapless Playback";
796 struct mixer_ctl *ctl;
797
798 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700799 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530800
801 /*Disable gapless if its AV playback*/
802 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800803
804 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
805 if (!ctl) {
806 ALOGE("%s: Could not get ctl for mixer cmd - %s",
807 __func__, mixer_ctl_name);
808 return -EINVAL;
809 }
810
811 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
812 ALOGE("%s: Could not set gapless mode %d",
813 __func__, gapless_enabled);
814 return -EINVAL;
815 }
816 return 0;
817}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700818
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700819__attribute__ ((visibility ("default")))
820int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
821 int table_size) {
822 int ret_val = 0;
823 ALOGV("%s: enter ... ", __func__);
824
825 pthread_mutex_lock(&adev_init_lock);
826 if (adev == NULL) {
827 ALOGW("%s: adev is NULL .... ", __func__);
828 goto done;
829 }
830
831 pthread_mutex_lock(&adev->lock);
832 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
833 pthread_mutex_unlock(&adev->lock);
834done:
835 pthread_mutex_unlock(&adev_init_lock);
836 ALOGV("%s: exit ... ", __func__);
837 return ret_val;
838}
839
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800840bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800841{
842 bool ret = false;
843 ALOGV("%s: enter ...", __func__);
844
845 pthread_mutex_lock(&adev_init_lock);
846
847 if (adev != NULL && adev->platform != NULL) {
848 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800849 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800850 pthread_mutex_unlock(&adev->lock);
851 }
852
853 pthread_mutex_unlock(&adev_init_lock);
854
855 ALOGV("%s: exit with ret %d", __func__, ret);
856 return ret;
857}
Aalique Grahame22e49102018-12-18 14:23:57 -0800858
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700859static bool is_supported_format(audio_format_t format)
860{
Eric Laurent86e17132013-09-12 17:49:30 -0700861 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530862 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530863 format == AUDIO_FORMAT_AAC_LC ||
864 format == AUDIO_FORMAT_AAC_HE_V1 ||
865 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530866 format == AUDIO_FORMAT_AAC_ADTS_LC ||
867 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
868 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530869 format == AUDIO_FORMAT_AAC_LATM_LC ||
870 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
871 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530872 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
873 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530874 format == AUDIO_FORMAT_PCM_FLOAT ||
875 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700876 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530877 format == AUDIO_FORMAT_AC3 ||
878 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700879 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530880 format == AUDIO_FORMAT_DTS ||
881 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800882 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530883 format == AUDIO_FORMAT_ALAC ||
884 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530885 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530886 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800887 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530888 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700889 format == AUDIO_FORMAT_APTX ||
890 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800891 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700892
893 return false;
894}
895
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700896static inline bool is_mmap_usecase(audio_usecase_t uc_id)
897{
898 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800899 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700900 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
901}
902
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700903static inline bool is_valid_volume(float left, float right)
904{
905 return ((left >= 0.0f && right >= 0.0f) ? true : false);
906}
907
Avinash Vaish71a8b972014-07-24 15:36:33 +0530908static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
909 struct audio_usecase *uc_info)
910{
911 struct listnode *node;
912 struct audio_usecase *usecase;
913
914 if (uc_info == NULL)
915 return -EINVAL;
916
917 /* Re-route all voice usecases on the shared backend other than the
918 specified usecase to new snd devices */
919 list_for_each(node, &adev->usecase_list) {
920 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800921 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530922 enable_audio_route(adev, usecase);
923 }
924 return 0;
925}
926
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530927static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530928{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530929 ALOGV("%s", __func__);
930 audio_route_apply_and_update_path(adev->audio_route,
931 "asrc-mode");
932 adev->asrc_mode_enabled = true;
933}
934
935static void disable_asrc_mode(struct audio_device *adev)
936{
937 ALOGV("%s", __func__);
938 audio_route_reset_and_update_path(adev->audio_route,
939 "asrc-mode");
940 adev->asrc_mode_enabled = false;
941}
942
Saurav Kumarc1411662020-10-14 10:50:45 +0530943static void check_and_configure_headphone(struct audio_device *adev,
944 struct audio_usecase *uc_info,
945 snd_device_t snd_device)
946{
947 struct listnode *node;
948 struct audio_usecase *usecase;
949 int new_backend_idx, usecase_backend_idx;
950 bool spkr_hph_single_be_native_concurrency;
951
952 new_backend_idx = platform_get_backend_index(snd_device);
953 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
954 if ( spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) {
955 list_for_each(node, &adev->usecase_list) {
956 usecase = node_to_item(node, struct audio_usecase, list);
957 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
958 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
959 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
960 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
961 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
962 disable_audio_route(adev, usecase);
963 disable_snd_device(adev, usecase->out_snd_device);
964 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530965 platform_check_and_set_codec_backend_cfg(adev, usecase,
966 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530967 enable_audio_route(adev, usecase);
968 enable_snd_device(adev, usecase->out_snd_device);
969 }
970 }
971 }
972 }
973}
974
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530975/*
976 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
977 * 44.1 or Native DSD backends are enabled for any of current use case.
978 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
979 * - Disable current mix path use case(Headphone backend) and re-enable it with
980 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
981 * e.g. Naitve DSD or Headphone 44.1 -> + 48
982 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530983static void check_and_set_asrc_mode(struct audio_device *adev,
984 struct audio_usecase *uc_info,
985 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530986{
987 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530988 int i, num_new_devices = 0;
989 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
990 /*
991 *Split snd device for new combo use case
992 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
993 */
994 if (platform_split_snd_device(adev->platform,
995 snd_device,
996 &num_new_devices,
997 split_new_snd_devices) == 0) {
998 for (i = 0; i < num_new_devices; i++)
999 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1000 } else {
1001 int new_backend_idx = platform_get_backend_index(snd_device);
1002 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1003 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1004 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1005 !adev->asrc_mode_enabled) {
1006 struct listnode *node = NULL;
1007 struct audio_usecase *uc = NULL;
1008 struct stream_out *curr_out = NULL;
1009 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1010 int i, num_devices, ret = 0;
1011 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301012
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301013 list_for_each(node, &adev->usecase_list) {
1014 uc = node_to_item(node, struct audio_usecase, list);
1015 curr_out = (struct stream_out*) uc->stream.out;
1016 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1017 /*
1018 *Split snd device for existing combo use case
1019 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1020 */
1021 ret = platform_split_snd_device(adev->platform,
1022 uc->out_snd_device,
1023 &num_devices,
1024 split_snd_devices);
1025 if (ret < 0 || num_devices == 0) {
1026 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1027 split_snd_devices[0] = uc->out_snd_device;
1028 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001029 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301030 for (i = 0; i < num_devices; i++) {
1031 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1032 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1033 if((new_backend_idx == HEADPHONE_BACKEND) &&
1034 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1035 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001036 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301037 __func__);
1038 enable_asrc_mode(adev);
1039 break;
1040 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1041 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1042 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001043 ALOGV("%s: 48K stream detected, disabling and enabling it \
1044 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301045 disable_audio_route(adev, uc);
1046 disable_snd_device(adev, uc->out_snd_device);
1047 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1048 if (new_backend_idx == DSD_NATIVE_BACKEND)
1049 audio_route_apply_and_update_path(adev->audio_route,
1050 "hph-true-highquality-mode");
1051 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1052 (curr_out->bit_width >= 24))
1053 audio_route_apply_and_update_path(adev->audio_route,
1054 "hph-highquality-mode");
1055 enable_asrc_mode(adev);
1056 enable_snd_device(adev, uc->out_snd_device);
1057 enable_audio_route(adev, uc);
1058 break;
1059 }
1060 }
1061 // reset split devices count
1062 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001063 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301064 if (adev->asrc_mode_enabled)
1065 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301066 }
1067 }
1068 }
1069}
1070
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001071static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1072 struct audio_effect_config effect_config,
1073 unsigned int param_value)
1074{
1075 char mixer_ctl_name[] = "Audio Effect";
1076 struct mixer_ctl *ctl;
1077 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001078 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001079
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001080 if (in == NULL) {
1081 ALOGE("%s: active input stream is NULL", __func__);
1082 return -EINVAL;
1083 }
1084
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001085 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1086 if (!ctl) {
1087 ALOGE("%s: Could not get mixer ctl - %s",
1088 __func__, mixer_ctl_name);
1089 return -EINVAL;
1090 }
1091
1092 set_values[0] = 1; //0:Rx 1:Tx
1093 set_values[1] = in->app_type_cfg.app_type;
1094 set_values[2] = (long)effect_config.module_id;
1095 set_values[3] = (long)effect_config.instance_id;
1096 set_values[4] = (long)effect_config.param_id;
1097 set_values[5] = param_value;
1098
1099 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1100
1101 return 0;
1102
1103}
1104
1105static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1106 int effect_type, unsigned int *param_value)
1107{
1108 int ret = 0;
1109 struct audio_effect_config other_effect_config;
1110 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001111 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001112
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001113 if (in == NULL) {
1114 ALOGE("%s: active input stream is NULL", __func__);
1115 return -EINVAL;
1116 }
1117
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001118 usecase = get_usecase_from_list(adev, in->usecase);
1119 if (!usecase)
1120 return -EINVAL;
1121
1122 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1123 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1124 if (ret < 0) {
1125 ALOGE("%s Failed to get effect params %d", __func__, ret);
1126 return ret;
1127 }
1128
1129 if (module_id == other_effect_config.module_id) {
1130 //Same module id for AEC/NS. Values need to be combined
1131 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1132 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1133 *param_value |= other_effect_config.param_value;
1134 }
1135 }
1136
1137 return ret;
1138}
1139
1140static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301141{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001142 struct audio_effect_config effect_config;
1143 struct audio_usecase *usecase = NULL;
1144 int ret = 0;
1145 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001146 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001148 if(!voice_extn_is_dynamic_ecns_enabled())
1149 return ENOSYS;
1150
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001151 if (!in) {
1152 ALOGE("%s: Invalid input stream", __func__);
1153 return -EINVAL;
1154 }
1155
1156 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1157
1158 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001159 if (usecase == NULL) {
1160 ALOGE("%s: Could not find the usecase (%d) in the list",
1161 __func__, in->usecase);
1162 return -EINVAL;
1163 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001164
1165 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1166 if (ret < 0) {
1167 ALOGE("%s Failed to get module id %d", __func__, ret);
1168 return ret;
1169 }
1170 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1171 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1172
1173 if(enable)
1174 param_value = effect_config.param_value;
1175
1176 /*Special handling for AEC & NS effects Param values need to be
1177 updated if module ids are same*/
1178
1179 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1180 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1181 if (ret < 0)
1182 return ret;
1183 }
1184
1185 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1186
1187 return ret;
1188}
1189
1190static void check_and_enable_effect(struct audio_device *adev)
1191{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001192 if(!voice_extn_is_dynamic_ecns_enabled())
1193 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001194
Eric Laurent637e2d42018-11-15 12:24:31 -08001195 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001196
Eric Laurent637e2d42018-11-15 12:24:31 -08001197 if (in != NULL && !in->standby) {
1198 if (in->enable_aec)
1199 enable_disable_effect(adev, EFFECT_AEC, true);
1200
1201 if (in->enable_ns &&
1202 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1203 enable_disable_effect(adev, EFFECT_NS, true);
1204 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001205 }
1206}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001207
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001208int pcm_ioctl(struct pcm *pcm, int request, ...)
1209{
1210 va_list ap;
1211 void * arg;
1212 int pcm_fd = *(int*)pcm;
1213
1214 va_start(ap, request);
1215 arg = va_arg(ap, void *);
1216 va_end(ap);
1217
1218 return ioctl(pcm_fd, request, arg);
1219}
1220
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001221int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001225 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301226 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301227 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001228 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301229 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001230
1231 if (usecase == NULL)
1232 return -EINVAL;
1233
1234 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1235
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 if (usecase->type == PCM_CAPTURE) {
1237 struct stream_in *in = usecase->stream.in;
1238 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001239 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001240
1241 if (in) {
1242 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001243 list_init(&out_devices);
1244 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001245 struct listnode *node;
1246 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1247 USECASE_AUDIO_PLAYBACK_VOIP);
1248 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001249 assign_devices(&out_devices,
1250 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001251 } else if (adev->primary_output &&
1252 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001253 assign_devices(&out_devices,
1254 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001255 } else {
1256 list_for_each(node, &adev->usecase_list) {
1257 uinfo = node_to_item(node, struct audio_usecase, list);
1258 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001259 assign_devices(&out_devices,
1260 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001261 break;
1262 }
1263 }
1264 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001265
1266 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001267 in->ec_opened = true;
1268 }
1269 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001270 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1271 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1272 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001273 snd_device = usecase->in_snd_device;
1274 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001276 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001277
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001278#ifdef DS1_DOLBY_DAP_ENABLED
1279 audio_extn_dolby_set_dmid(adev);
1280 audio_extn_dolby_set_endpoint(adev);
1281#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001282 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001283 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301284 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001285 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001286 if (audio_extn_is_maxx_audio_enabled())
1287 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301288 audio_extn_utils_send_audio_calibration(adev, usecase);
Weiyin Jiange645ada2020-11-09 14:08:59 +08001289 if ((usecase->type == PCM_PLAYBACK) &&
1290 ((out = usecase->stream.out) != NULL)) {
1291 if (!is_offload_usecase(out->usecase)) {
1292 pthread_mutex_lock(&out->latch_lock);
1293 out->muted = false;
1294 pthread_mutex_unlock(&out->latch_lock);
1295 } else if (out->compr) {
Manish Dewangan58229382017-02-02 15:48:41 +05301296 audio_extn_utils_compress_set_clk_rec_mode(usecase);
Weiyin Jiange645ada2020-11-09 14:08:59 +08001297 }
Manish Dewangan58229382017-02-02 15:48:41 +05301298 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301299
1300 if (usecase->type == PCM_CAPTURE) {
1301 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001302 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301303 ALOGD("%s: set custom mtmx params v1", __func__);
1304 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1305 }
1306 } else {
1307 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1308 }
Manish Dewangan58229382017-02-02 15:48:41 +05301309
Andy Hung756ecc12018-10-19 17:47:12 -07001310 // we shouldn't truncate mixer_path
1311 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1312 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1313 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001314 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001315 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301316 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1317 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1318 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1319 if (parms) {
1320 audio_extn_fm_set_parameters(adev, parms);
1321 str_parms_destroy(parms);
1322 }
1323 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 ALOGV("%s: exit", __func__);
1325 return 0;
1326}
1327
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001328int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001329 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001331 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001332 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301333 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001334
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301335 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001336 return -EINVAL;
1337
1338 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301339 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 snd_device = usecase->in_snd_device;
1341 else
1342 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001343
1344 /* disable island and power mode on supported device for voice call */
1345 if (usecase->type == VOICE_CALL) {
1346 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1347 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1348 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1349 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1350 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1351 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001352 if (voice_is_lte_call_active(adev))
1353 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001354 ALOGD("%s: disable island cfg and power mode in voice tx path",
1355 __func__);
1356 }
1357 }
1358 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1359 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1360 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1361 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1362 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1363 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1364 ALOGD("%s: disable island cfg and power mode in voice rx path",
1365 __func__);
1366 }
1367 }
1368 }
1369
Andy Hung756ecc12018-10-19 17:47:12 -07001370 // we shouldn't truncate mixer_path
1371 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1372 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1373 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001374 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001375 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001376 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001377 if (usecase->type == PCM_CAPTURE) {
1378 struct stream_in *in = usecase->stream.in;
1379 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001380 struct listnode out_devices;
1381 list_init(&out_devices);
1382 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001383 in->ec_opened = false;
1384 }
1385 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001386 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301387 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301388
1389 if (usecase->type == PCM_CAPTURE) {
1390 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001391 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301392 ALOGD("%s: reset custom mtmx params v1", __func__);
1393 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1394 }
1395 } else {
1396 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1397 }
1398
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001399 if ((usecase->type == PCM_PLAYBACK) &&
1400 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301401 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403 ALOGV("%s: exit", __func__);
1404 return 0;
1405}
1406
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001407int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001408 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301410 int i, num_devices = 0;
1411 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001412 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1413
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001414 if (snd_device < SND_DEVICE_MIN ||
1415 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001416 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001417 return -EINVAL;
1418 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001419
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001420 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001421 ALOGE("%s: Invalid sound device returned", __func__);
1422 return -EINVAL;
1423 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001424
1425 adev->snd_dev_ref_cnt[snd_device]++;
1426
1427 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1428 (platform_split_snd_device(adev->platform,
1429 snd_device,
1430 &num_devices,
1431 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001432 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001433 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001434 /* Set backend config for A2DP to ensure slimbus configuration
1435 is correct if A2DP is already active and backend is closed
1436 and re-opened */
1437 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1438 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 return 0;
1440 }
1441
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001442 if (audio_extn_spkr_prot_is_enabled())
1443 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001444
Aalique Grahame22e49102018-12-18 14:23:57 -08001445 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1446
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001447 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1448 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001449 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1450 goto err;
1451 }
1452 audio_extn_dev_arbi_acquire(snd_device);
1453 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001454 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001455 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001456 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001457 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001458 } else if (platform_split_snd_device(adev->platform,
1459 snd_device,
1460 &num_devices,
1461 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301462 for (i = 0; i < num_devices; i++) {
1463 enable_snd_device(adev, new_snd_devices[i]);
1464 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001465 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001466 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001467 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301468
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001469 /* enable island and power mode on supported device */
1470 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1471 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1472 platform_set_island_cfg_on_device(adev, snd_device, true);
1473 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001474 if (voice_is_lte_call_active(adev) &&
1475 (snd_device >= SND_DEVICE_IN_BEGIN &&
1476 snd_device < SND_DEVICE_IN_END))
1477 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001478 ALOGD("%s: enable island cfg and power mode on: %s",
1479 __func__, device_name);
1480 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301481
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301482 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1483 if (audio_extn_a2dp_start_playback() < 0) {
1484 ALOGE(" fail to configure A2dp Source control path ");
1485 goto err;
1486 } else {
1487 adev->a2dp_started = true;
1488 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001489 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001490
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001491 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1492 (audio_extn_a2dp_start_capture() < 0)) {
1493 ALOGE(" fail to configure A2dp Sink control path ");
1494 goto err;
1495 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301496
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001497 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1498 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1499 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1500 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1501 ALOGE(" fail to configure sco control path ");
1502 goto err;
1503 }
Zhou Song12c29502019-03-16 10:37:18 +08001504 }
1505
Zhou Song331c8e52019-08-26 14:16:12 +08001506 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001507 /* due to the possibility of calibration overwrite between listen
1508 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001509 audio_extn_sound_trigger_update_device_status(snd_device,
1510 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301511 audio_extn_listen_update_device_status(snd_device,
1512 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001513 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001514 audio_extn_sound_trigger_update_device_status(snd_device,
1515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301516 audio_extn_listen_update_device_status(snd_device,
1517 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001518 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301522
1523 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1524 !adev->native_playback_enabled &&
1525 audio_is_true_native_stream_active(adev)) {
1526 ALOGD("%s: %d: napb: enabling native mode in hardware",
1527 __func__, __LINE__);
1528 audio_route_apply_and_update_path(adev->audio_route,
1529 "true-native-mode");
1530 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301531 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301532 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1533 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001534 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001535 ALOGD("%s: init ec ref loopback", __func__);
1536 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001540err:
1541 adev->snd_dev_ref_cnt[snd_device]--;
1542 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543}
1544
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001545int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001546 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301548 int i, num_devices = 0;
1549 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001550 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1551
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001552 if (snd_device < SND_DEVICE_MIN ||
1553 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001554 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001555 return -EINVAL;
1556 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001557
1558 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1559 ALOGE("%s: Invalid sound device returned", __func__);
1560 return -EINVAL;
1561 }
1562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1564 ALOGE("%s: device ref cnt is already 0", __func__);
1565 return -EINVAL;
1566 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001567
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001569
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001572 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301573
Aalique Grahame22e49102018-12-18 14:23:57 -08001574 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1575
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001576 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1577 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001578 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001579
1580 // when speaker device is disabled, reset swap.
1581 // will be renabled on usecase start
1582 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001583 } else if (platform_split_snd_device(adev->platform,
1584 snd_device,
1585 &num_devices,
1586 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301587 for (i = 0; i < num_devices; i++) {
1588 disable_snd_device(adev, new_snd_devices[i]);
1589 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001590 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001591 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001592 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001593 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001594
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301595 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301596 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301597 adev->a2dp_started = false;
1598 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001599 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001600 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001601 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301602 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001603 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301604 adev->native_playback_enabled) {
1605 ALOGD("%s: %d: napb: disabling native mode in hardware",
1606 __func__, __LINE__);
1607 audio_route_reset_and_update_path(adev->audio_route,
1608 "true-native-mode");
1609 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001610 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301611 adev->asrc_mode_enabled) {
1612 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301613 disable_asrc_mode(adev);
1614 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001615 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301616 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001617 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001618 ALOGD("%s: deinit ec ref loopback", __func__);
1619 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1620 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001621
1622 audio_extn_utils_release_snd_device(snd_device);
1623 } else {
1624 if (platform_split_snd_device(adev->platform,
1625 snd_device,
1626 &num_devices,
1627 new_snd_devices) == 0) {
1628 for (i = 0; i < num_devices; i++) {
1629 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1630 }
1631 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001632 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 return 0;
1635}
1636
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001637/*
1638 legend:
1639 uc - existing usecase
1640 new_uc - new usecase
1641 d1, d11, d2 - SND_DEVICE enums
1642 a1, a2 - corresponding ANDROID device enums
1643 B1, B2 - backend strings
1644
1645case 1
1646 uc->dev d1 (a1) B1
1647 new_uc->dev d1 (a1), d2 (a2) B1, B2
1648
1649 resolution: disable and enable uc->dev on d1
1650
1651case 2
1652 uc->dev d1 (a1) B1
1653 new_uc->dev d11 (a1) B1
1654
1655 resolution: need to switch uc since d1 and d11 are related
1656 (e.g. speaker and voice-speaker)
1657 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1658
1659case 3
1660 uc->dev d1 (a1) B1
1661 new_uc->dev d2 (a2) B2
1662
1663 resolution: no need to switch uc
1664
1665case 4
1666 uc->dev d1 (a1) B1
1667 new_uc->dev d2 (a2) B1
1668
1669 resolution: disable enable uc-dev on d2 since backends match
1670 we cannot enable two streams on two different devices if they
1671 share the same backend. e.g. if offload is on speaker device using
1672 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1673 using the same backend, offload must also be switched to voice-handset.
1674
1675case 5
1676 uc->dev d1 (a1) B1
1677 new_uc->dev d1 (a1), d2 (a2) B1
1678
1679 resolution: disable enable uc-dev on d2 since backends match
1680 we cannot enable two streams on two different devices if they
1681 share the same backend.
1682
1683case 6
1684 uc->dev d1 (a1) B1
1685 new_uc->dev d2 (a1) B2
1686
1687 resolution: no need to switch
1688
1689case 7
1690 uc->dev d1 (a1), d2 (a2) B1, B2
1691 new_uc->dev d1 (a1) B1
1692
1693 resolution: no need to switch
1694
Zhou Song4ba65882018-07-09 14:48:07 +08001695case 8
1696 uc->dev d1 (a1) B1
1697 new_uc->dev d11 (a1), d2 (a2) B1, B2
1698 resolution: compared to case 1, for this case, d1 and d11 are related
1699 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301700
1701case 9
1702 uc->dev d1 (a1), d2(a2) B1 B2
1703 new_uc->dev d1 (a1), d22 (a2) B1, B2
1704 resolution: disable enable uc-dev on d2 since backends match
1705 we cannot enable two streams on two different devices if they
1706 share the same backend. This is special case for combo use case
1707 with a2dp and sco devices which uses same backend.
1708 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001709*/
1710static snd_device_t derive_playback_snd_device(void * platform,
1711 struct audio_usecase *uc,
1712 struct audio_usecase *new_uc,
1713 snd_device_t new_snd_device)
1714{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001715 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001716
1717 snd_device_t d1 = uc->out_snd_device;
1718 snd_device_t d2 = new_snd_device;
1719
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001720 list_init(&a1);
1721 list_init(&a2);
1722
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301723 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301724 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001725 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1726 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301727 break;
1728 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001729 assign_devices(&a1, &uc->stream.out->device_list);
1730 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301731 break;
1732 }
1733
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001734 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001735 if (!compare_devices(&a1, &a2) &&
1736 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001737 snd_device_t d3[2];
1738 int num_devices = 0;
1739 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001740 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001741 &num_devices,
1742 d3);
1743 if (ret < 0) {
1744 if (ret != -ENOSYS) {
1745 ALOGW("%s failed to split snd_device %d",
1746 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001747 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001748 }
1749 goto end;
1750 }
1751
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001752 if (platform_check_backends_match(d3[0], d3[1])) {
1753 return d2; // case 5
1754 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301755 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1756 platform_check_backends_match(d1, d2))
1757 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001758 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301759 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001760 // check if d1 is related to any of d3's
1761 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001762 return d1; // case 1
1763 else
1764 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001765 }
1766 } else {
1767 if (platform_check_backends_match(d1, d2)) {
1768 return d2; // case 2, 4
1769 } else {
1770 return d1; // case 6, 3
1771 }
1772 }
1773
1774end:
1775 return d2; // return whatever was calculated before.
1776}
1777
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001778static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301779 struct audio_usecase *uc_info,
1780 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001781{
1782 struct listnode *node;
1783 struct audio_usecase *usecase;
1784 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301785 snd_device_t uc_derive_snd_device;
1786 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001787 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1788 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001789 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301790 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001791 /*
1792 * This function is to make sure that all the usecases that are active on
1793 * the hardware codec backend are always routed to any one device that is
1794 * handled by the hardware codec.
1795 * For example, if low-latency and deep-buffer usecases are currently active
1796 * on speaker and out_set_parameters(headset) is received on low-latency
1797 * output, then we have to make sure deep-buffer is also switched to headset,
1798 * because of the limitation that both the devices cannot be enabled
1799 * at the same time as they share the same backend.
1800 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001801 /*
1802 * This call is to check if we need to force routing for a particular stream
1803 * If there is a backend configuration change for the device when a
1804 * new stream starts, then ADM needs to be closed and re-opened with the new
1805 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001806 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001807 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001808 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1809 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301810 /* For a2dp device reconfigure all active sessions
1811 * with new AFE encoder format based on a2dp state
1812 */
1813 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301814 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1815 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301816 audio_extn_a2dp_is_force_device_switch()) {
1817 force_routing = true;
1818 force_restart_session = true;
1819 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001820
1821 /*
1822 * Island cfg and power mode config needs to set before AFE port start.
1823 * Set force routing in case of voice device was enable before.
1824 */
1825 if (uc_info->type == VOICE_CALL &&
1826 voice_extn_is_voice_power_mode_supported() &&
1827 platform_check_and_update_island_power_status(adev->platform,
1828 uc_info,
1829 snd_device)) {
1830 force_routing = true;
1831 ALOGD("%s:becf: force routing %d for power mode supported device",
1832 __func__, force_routing);
1833 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301834 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001837 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001838 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001839 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1840 switch_device[i] = false;
1841
1842 list_for_each(node, &adev->usecase_list) {
1843 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001844
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301845 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1846 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301847 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301848 platform_get_snd_device_name(usecase->out_snd_device),
1849 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301850 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1851 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301852 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1853 usecase, uc_info, snd_device);
1854 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001855 (is_codec_backend_out_device_type(&usecase->device_list) ||
1856 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1857 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1858 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1859 is_a2dp_out_device_type(&usecase->device_list) ||
1860 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301861 ((force_restart_session) ||
1862 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301863 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1864 __func__, use_case_table[usecase->id],
1865 platform_get_snd_device_name(usecase->out_snd_device));
1866 disable_audio_route(adev, usecase);
1867 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301868 /* Enable existing usecase on derived playback device */
1869 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301870 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872 }
1873 }
1874
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301875 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1876 num_uc_to_switch);
1877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001879 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301881 /* Make sure the previous devices to be disabled first and then enable the
1882 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 list_for_each(node, &adev->usecase_list) {
1884 usecase = node_to_item(node, struct audio_usecase, list);
1885 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001886 /* Check if output sound device to be switched can be split and if any
1887 of the split devices match with derived sound device */
1888 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1889 &num_devices, split_snd_devices) == 0) {
1890 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1891 for (i = 0; i < num_devices; i++) {
1892 /* Disable devices that do not match with derived sound device */
1893 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1894 disable_snd_device(adev, split_snd_devices[i]);
1895 }
1896 } else {
1897 disable_snd_device(adev, usecase->out_snd_device);
1898 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899 }
1900 }
1901
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001902 list_for_each(node, &adev->usecase_list) {
1903 usecase = node_to_item(node, struct audio_usecase, list);
1904 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001905 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1906 &num_devices, split_snd_devices) == 0) {
1907 /* Enable derived sound device only if it does not match with
1908 one of the split sound devices. This is because the matching
1909 sound device was not disabled */
1910 bool should_enable = true;
1911 for (i = 0; i < num_devices; i++) {
1912 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1913 should_enable = false;
1914 break;
1915 }
1916 }
1917 if (should_enable)
1918 enable_snd_device(adev, derive_snd_device[usecase->id]);
1919 } else {
1920 enable_snd_device(adev, derive_snd_device[usecase->id]);
1921 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001922 }
1923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 /* Re-route all the usecases on the shared backend other than the
1926 specified usecase to new snd devices */
1927 list_for_each(node, &adev->usecase_list) {
1928 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301929 /* Update the out_snd_device only before enabling the audio route */
1930 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301931 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301932 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301933 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301934 use_case_table[usecase->id],
1935 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001936 /* Update voc calibration before enabling VoIP route */
1937 if (usecase->type == VOIP_CALL)
1938 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001939 usecase->out_snd_device,
1940 platform_get_input_snd_device(
1941 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301942 &uc_info->device_list,
1943 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301944 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301945 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001946 out_set_voip_volume(&usecase->stream.out->stream,
1947 usecase->stream.out->volume_l,
1948 usecase->stream.out->volume_r);
1949 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301950 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001951 }
1952 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001953 }
1954}
1955
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301956static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001957 struct audio_usecase *uc_info,
1958 snd_device_t snd_device)
1959{
1960 struct listnode *node;
1961 struct audio_usecase *usecase;
1962 bool switch_device[AUDIO_USECASE_MAX];
1963 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001964 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001965 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001966
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301967 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1968 snd_device);
1969 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301970
1971 /*
1972 * Make sure out devices is checked against out codec backend device and
1973 * also in devices against in codec backend. Checking out device against in
1974 * codec backend or vice versa causes issues.
1975 */
1976 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001977 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001978
1979 /*
1980 * Island cfg and power mode config needs to set before AFE port start.
1981 * Set force routing in case of voice device was enable before.
1982 */
1983
1984 if (uc_info->type == VOICE_CALL &&
1985 voice_extn_is_voice_power_mode_supported() &&
1986 platform_check_and_update_island_power_status(adev->platform,
1987 uc_info,
1988 snd_device)) {
1989 force_routing = true;
1990 ALOGD("%s:becf: force routing %d for power mode supported device",
1991 __func__, force_routing);
1992 }
1993
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001994 /*
1995 * This function is to make sure that all the active capture usecases
1996 * are always routed to the same input sound device.
1997 * For example, if audio-record and voice-call usecases are currently
1998 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1999 * is received for voice call then we have to make sure that audio-record
2000 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2001 * because of the limitation that two devices cannot be enabled
2002 * at the same time if they share the same backend.
2003 */
2004 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2005 switch_device[i] = false;
2006
2007 list_for_each(node, &adev->usecase_list) {
2008 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302009 /*
2010 * TODO: Enhance below condition to handle BT sco/USB multi recording
2011 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302012
2013 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2014 (usecase->in_snd_device != snd_device || force_routing));
2015 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2016 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2017 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002018 ((backend_check_cond &&
2019 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002020 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002021 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002022 is_single_device_type_equal(&usecase->device_list,
2023 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002024 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002025 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002026 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302027 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002028 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002029 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002030 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002031 switch_device[usecase->id] = true;
2032 num_uc_to_switch++;
2033 }
2034 }
2035
2036 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002037 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002038
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302039 /* Make sure the previous devices to be disabled first and then enable the
2040 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002041 list_for_each(node, &adev->usecase_list) {
2042 usecase = node_to_item(node, struct audio_usecase, list);
2043 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002044 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002045 }
2046 }
2047
2048 list_for_each(node, &adev->usecase_list) {
2049 usecase = node_to_item(node, struct audio_usecase, list);
2050 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002051 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002052 }
2053 }
2054
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002055 /* Re-route all the usecases on the shared backend other than the
2056 specified usecase to new snd devices */
2057 list_for_each(node, &adev->usecase_list) {
2058 usecase = node_to_item(node, struct audio_usecase, list);
2059 /* Update the in_snd_device only before enabling the audio route */
2060 if (switch_device[usecase->id] ) {
2061 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002062 if (usecase->type != VOICE_CALL) {
2063 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302064 if (usecase->type == VOIP_CALL) {
2065 snd_device_t voip_snd_device;
2066 voip_snd_device = platform_get_output_snd_device(adev->platform,
2067 uc_info->stream.out,
2068 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002069 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302070 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002071 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302072 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302073 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002074 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002075 }
2076 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002077 }
2078}
2079
Mingming Yin3a941d42016-02-17 18:08:05 -08002080static void reset_hdmi_sink_caps(struct stream_out *out) {
2081 int i = 0;
2082
2083 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2084 out->supported_channel_masks[i] = 0;
2085 }
2086 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2087 out->supported_formats[i] = 0;
2088 }
2089 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2090 out->supported_sample_rates[i] = 0;
2091 }
2092}
2093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002095static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096{
Mingming Yin3a941d42016-02-17 18:08:05 -08002097 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002098 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2099 out->extconn.cs.controller,
2100 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101
Mingming Yin3a941d42016-02-17 18:08:05 -08002102 reset_hdmi_sink_caps(out);
2103
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002104 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002105 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002106 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002107 out->extconn.cs.stream);
2108 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002109 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002110 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002111 }
2112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002115 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002116 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002117 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2118 case 6:
2119 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2120 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2121 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2122 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2123 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2124 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 break;
2126 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002127 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002128 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 break;
2130 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002131
2132 // check channel format caps
2133 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002134 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2135 out->extconn.cs.controller,
2136 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002137 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2138 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2139 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2140 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2141 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2142 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2143 }
2144
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002145 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2146 out->extconn.cs.controller,
2147 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002148 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2149 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2150 }
2151
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002152 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2153 out->extconn.cs.controller,
2154 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002155 ALOGV(":%s HDMI supports DTS format", __func__);
2156 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2157 }
2158
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002159 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2160 out->extconn.cs.controller,
2161 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002162 ALOGV(":%s HDMI supports DTS HD format", __func__);
2163 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2164 }
2165
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002166 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2167 out->extconn.cs.controller,
2168 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002169 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2170 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2171 }
2172
Mingming Yin3a941d42016-02-17 18:08:05 -08002173
2174 // check sample rate caps
2175 i = 0;
2176 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002177 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2178 out->extconn.cs.controller,
2179 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002180 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2181 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2182 }
2183 }
2184
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002185 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186}
2187
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002188static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2189 uint32_t *supported_sample_rates __unused,
2190 uint32_t max_rates __unused)
2191{
2192 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2193 supported_sample_rates,
2194 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302195 ssize_t i = 0;
2196
2197 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002198 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2199 supported_sample_rates[i]);
2200 }
2201 return count;
2202}
2203
2204static inline int read_usb_sup_channel_masks(bool is_playback,
2205 audio_channel_mask_t *supported_channel_masks,
2206 uint32_t max_masks)
2207{
2208 int channels = audio_extn_usb_get_max_channels(is_playback);
2209 int channel_count;
2210 uint32_t num_masks = 0;
2211 if (channels > MAX_HIFI_CHANNEL_COUNT)
2212 channels = MAX_HIFI_CHANNEL_COUNT;
2213
2214 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002215 // start from 2 channels as framework currently doesn't support mono.
2216 if (channels >= FCC_2) {
2217 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2218 }
2219 for (channel_count = FCC_2;
2220 channel_count <= channels && num_masks < max_masks;
2221 ++channel_count) {
2222 supported_channel_masks[num_masks++] =
2223 audio_channel_mask_for_index_assignment_from_count(channel_count);
2224 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002225 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002226 // For capture we report all supported channel masks from 1 channel up.
2227 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002228 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2229 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002230 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2231 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2232 if (channel_count <= FCC_2) {
2233 mask = audio_channel_in_mask_from_count(channel_count);
2234 supported_channel_masks[num_masks++] = mask;
2235 }
2236 const audio_channel_mask_t index_mask =
2237 audio_channel_mask_for_index_assignment_from_count(channel_count);
2238 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2239 supported_channel_masks[num_masks++] = index_mask;
2240 }
2241 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002242 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302243
vincenttewf51c94e2019-05-07 10:28:53 +08002244 for (size_t i = 0; i < num_masks; ++i) {
2245 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2246 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302247 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002248 return num_masks;
2249}
2250
2251static inline int read_usb_sup_formats(bool is_playback __unused,
2252 audio_format_t *supported_formats,
2253 uint32_t max_formats __unused)
2254{
2255 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2256 switch (bitwidth) {
2257 case 24:
2258 // XXX : usb.c returns 24 for s24 and s24_le?
2259 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2260 break;
2261 case 32:
2262 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2263 break;
2264 case 16:
2265 default :
2266 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2267 break;
2268 }
2269 ALOGV("%s: %s supported format %d", __func__,
2270 is_playback ? "P" : "C", bitwidth);
2271 return 1;
2272}
2273
2274static inline int read_usb_sup_params_and_compare(bool is_playback,
2275 audio_format_t *format,
2276 audio_format_t *supported_formats,
2277 uint32_t max_formats,
2278 audio_channel_mask_t *mask,
2279 audio_channel_mask_t *supported_channel_masks,
2280 uint32_t max_masks,
2281 uint32_t *rate,
2282 uint32_t *supported_sample_rates,
2283 uint32_t max_rates) {
2284 int ret = 0;
2285 int num_formats;
2286 int num_masks;
2287 int num_rates;
2288 int i;
2289
2290 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2291 max_formats);
2292 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2293 max_masks);
2294
2295 num_rates = read_usb_sup_sample_rates(is_playback,
2296 supported_sample_rates, max_rates);
2297
2298#define LUT(table, len, what, dflt) \
2299 for (i=0; i<len && (table[i] != what); i++); \
2300 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2301
2302 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2303 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2304 LUT(supported_sample_rates, num_rates, *rate, 0);
2305
2306#undef LUT
2307 return ret < 0 ? -EINVAL : 0; // HACK TBD
2308}
2309
Alexy Josephb1379942016-01-29 15:49:38 -08002310audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002311 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002312{
2313 struct audio_usecase *usecase;
2314 struct listnode *node;
2315
2316 list_for_each(node, &adev->usecase_list) {
2317 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002318 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002319 ALOGV("%s: usecase id %d", __func__, usecase->id);
2320 return usecase->id;
2321 }
2322 }
2323 return USECASE_INVALID;
2324}
2325
Alexy Josephb1379942016-01-29 15:49:38 -08002326struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002327 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002328{
2329 struct audio_usecase *usecase;
2330 struct listnode *node;
2331
2332 list_for_each(node, &adev->usecase_list) {
2333 usecase = node_to_item(node, struct audio_usecase, list);
2334 if (usecase->id == uc_id)
2335 return usecase;
2336 }
2337 return NULL;
2338}
2339
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302340/*
2341 * is a true native playback active
2342 */
2343bool audio_is_true_native_stream_active(struct audio_device *adev)
2344{
2345 bool active = false;
2346 int i = 0;
2347 struct listnode *node;
2348
2349 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2350 ALOGV("%s:napb: not in true mode or non hdphones device",
2351 __func__);
2352 active = false;
2353 goto exit;
2354 }
2355
2356 list_for_each(node, &adev->usecase_list) {
2357 struct audio_usecase *uc;
2358 uc = node_to_item(node, struct audio_usecase, list);
2359 struct stream_out *curr_out =
2360 (struct stream_out*) uc->stream.out;
2361
2362 if (curr_out && PCM_PLAYBACK == uc->type) {
2363 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2364 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2365 uc->id, curr_out->sample_rate,
2366 curr_out->bit_width,
2367 platform_get_snd_device_name(uc->out_snd_device));
2368
2369 if (is_offload_usecase(uc->id) &&
2370 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2371 active = true;
2372 ALOGD("%s:napb:native stream detected", __func__);
2373 }
2374 }
2375 }
2376exit:
2377 return active;
2378}
2379
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002380uint32_t adev_get_dsp_bit_width_enforce_mode()
2381{
2382 if (adev == NULL) {
2383 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2384 return 0;
2385 }
2386 return adev->dsp_bit_width_enforce_mode;
2387}
2388
2389static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2390{
2391 char value[PROPERTY_VALUE_MAX];
2392 int trial;
2393 uint32_t dsp_bit_width_enforce_mode = 0;
2394
2395 if (!mixer) {
2396 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2397 __func__);
2398 return 0;
2399 }
2400
2401 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2402 value, NULL) > 0) {
2403 trial = atoi(value);
2404 switch (trial) {
2405 case 16:
2406 dsp_bit_width_enforce_mode = 16;
2407 break;
2408 case 24:
2409 dsp_bit_width_enforce_mode = 24;
2410 break;
2411 case 32:
2412 dsp_bit_width_enforce_mode = 32;
2413 break;
2414 default:
2415 dsp_bit_width_enforce_mode = 0;
2416 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2417 break;
2418 }
2419 }
2420
2421 return dsp_bit_width_enforce_mode;
2422}
2423
2424static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2425 uint32_t enforce_mode,
2426 bool enable)
2427{
2428 struct mixer_ctl *ctl = NULL;
2429 const char *mixer_ctl_name = "ASM Bit Width";
2430 uint32_t asm_bit_width_mode = 0;
2431
2432 if (enforce_mode == 0) {
2433 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2434 return;
2435 }
2436
2437 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2438 if (!ctl) {
2439 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2440 __func__, mixer_ctl_name);
2441 return;
2442 }
2443
2444 if (enable)
2445 asm_bit_width_mode = enforce_mode;
2446 else
2447 asm_bit_width_mode = 0;
2448
2449 ALOGV("%s DSP bit width feature status is %d width=%d",
2450 __func__, enable, asm_bit_width_mode);
2451 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2452 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2453 asm_bit_width_mode);
2454
2455 return;
2456}
2457
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302458/*
2459 * if native DSD playback active
2460 */
2461bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2462{
2463 bool active = false;
2464 struct listnode *node = NULL;
2465 struct audio_usecase *uc = NULL;
2466 struct stream_out *curr_out = NULL;
2467
2468 list_for_each(node, &adev->usecase_list) {
2469 uc = node_to_item(node, struct audio_usecase, list);
2470 curr_out = (struct stream_out*) uc->stream.out;
2471
2472 if (curr_out && PCM_PLAYBACK == uc->type &&
2473 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2474 active = true;
2475 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302476 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302477 }
2478 }
2479 return active;
2480}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302481
2482static bool force_device_switch(struct audio_usecase *usecase)
2483{
2484 bool ret = false;
2485 bool is_it_true_mode = false;
2486
Zhou Song30f2c3e2018-02-08 14:02:15 +08002487 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302488 usecase->type == TRANSCODE_LOOPBACK_RX ||
2489 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002490 return false;
2491 }
2492
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002493 if(usecase->stream.out == NULL) {
2494 ALOGE("%s: stream.out is NULL", __func__);
2495 return false;
2496 }
2497
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302498 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002499 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002500 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2501 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302502 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2503 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2504 (!is_it_true_mode && adev->native_playback_enabled)){
2505 ret = true;
2506 ALOGD("napb: time to toggle native mode");
2507 }
2508 }
2509
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302510 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302511 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2512 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002513 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302514 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302515 ALOGD("Force a2dp device switch to update new encoder config");
2516 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002517 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302518
Florian Pfister1a84f312018-07-19 14:38:18 +02002519 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302520 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2521 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002522 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302523 return ret;
2524}
2525
Aalique Grahame22e49102018-12-18 14:23:57 -08002526static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2527{
2528 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2529}
2530
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302531bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2532{
2533 bool ret=false;
2534 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002535 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2536 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302537 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2538 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002539 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302540 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002541 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2542 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302543 ret = true;
2544
2545 return ret;
2546}
2547
2548bool is_a2dp_device(snd_device_t out_snd_device)
2549{
2550 bool ret=false;
2551 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2552 ret = true;
2553
2554 return ret;
2555}
2556
2557bool is_bt_soc_on(struct audio_device *adev)
2558{
2559 struct mixer_ctl *ctl;
2560 char *mixer_ctl_name = "BT SOC status";
2561 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2562 bool bt_soc_status = true;
2563 if (!ctl) {
2564 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2565 __func__, mixer_ctl_name);
2566 /*This is to ensure we dont break targets which dont have the kernel change*/
2567 return true;
2568 }
2569 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2570 ALOGD("BT SOC status: %d",bt_soc_status);
2571 return bt_soc_status;
2572}
2573
Zhou Song331c8e52019-08-26 14:16:12 +08002574static int configure_btsco_sample_rate(snd_device_t snd_device)
2575{
2576 struct mixer_ctl *ctl = NULL;
2577 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2578 char *rate_str = NULL;
2579 bool is_rx_dev = true;
2580
2581 if (is_btsco_device(snd_device, snd_device)) {
2582 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2583 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2584 if (!ctl_sr_tx || !ctl_sr_rx) {
2585 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2586 if (!ctl_sr)
2587 return -ENOSYS;
2588 }
2589
2590 switch (snd_device) {
2591 case SND_DEVICE_OUT_BT_SCO:
2592 rate_str = "KHZ_8";
2593 break;
2594 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2595 case SND_DEVICE_IN_BT_SCO_MIC:
2596 rate_str = "KHZ_8";
2597 is_rx_dev = false;
2598 break;
2599 case SND_DEVICE_OUT_BT_SCO_WB:
2600 rate_str = "KHZ_16";
2601 break;
2602 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2603 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2604 rate_str = "KHZ_16";
2605 is_rx_dev = false;
2606 break;
2607 default:
2608 return 0;
2609 }
2610
2611 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2612 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2613 return -ENOSYS;
2614 }
2615 return 0;
2616}
2617
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302618int out_standby_l(struct audio_stream *stream);
2619
Eric Laurent637e2d42018-11-15 12:24:31 -08002620struct stream_in *adev_get_active_input(const struct audio_device *adev)
2621{
2622 struct listnode *node;
2623 struct stream_in *last_active_in = NULL;
2624
2625 /* Get last added active input.
2626 * TODO: We may use a priority mechanism to pick highest priority active source */
2627 list_for_each(node, &adev->usecase_list)
2628 {
2629 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2630 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2631 last_active_in = usecase->stream.in;
2632 }
2633
2634 return last_active_in;
2635}
2636
2637struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2638{
2639 struct listnode *node;
2640
2641 /* First check active inputs with voice communication source and then
2642 * any input if audio mode is in communication */
2643 list_for_each(node, &adev->usecase_list)
2644 {
2645 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2646 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2647 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2648 return usecase->stream.in;
2649 }
2650 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2651 return adev_get_active_input(adev);
2652
2653 return NULL;
2654}
2655
Carter Hsu2e429db2019-05-14 18:50:52 +08002656/*
2657 * Aligned with policy.h
2658 */
2659static inline int source_priority(int inputSource)
2660{
2661 switch (inputSource) {
2662 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2663 return 9;
2664 case AUDIO_SOURCE_CAMCORDER:
2665 return 8;
2666 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2667 return 7;
2668 case AUDIO_SOURCE_UNPROCESSED:
2669 return 6;
2670 case AUDIO_SOURCE_MIC:
2671 return 5;
2672 case AUDIO_SOURCE_ECHO_REFERENCE:
2673 return 4;
2674 case AUDIO_SOURCE_FM_TUNER:
2675 return 3;
2676 case AUDIO_SOURCE_VOICE_RECOGNITION:
2677 return 2;
2678 case AUDIO_SOURCE_HOTWORD:
2679 return 1;
2680 default:
2681 break;
2682 }
2683 return 0;
2684}
2685
2686static struct stream_in *get_priority_input(struct audio_device *adev)
2687{
2688 struct listnode *node;
2689 struct audio_usecase *usecase;
2690 int last_priority = 0, priority;
2691 struct stream_in *priority_in = NULL;
2692 struct stream_in *in;
2693
2694 list_for_each(node, &adev->usecase_list) {
2695 usecase = node_to_item(node, struct audio_usecase, list);
2696 if (usecase->type == PCM_CAPTURE) {
2697 in = usecase->stream.in;
2698 if (!in)
2699 continue;
2700 priority = source_priority(in->source);
2701
2702 if (priority > last_priority) {
2703 last_priority = priority;
2704 priority_in = in;
2705 }
2706 }
2707 }
2708 return priority_in;
2709}
2710
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002711int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002713 snd_device_t out_snd_device = SND_DEVICE_NONE;
2714 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 struct audio_usecase *usecase = NULL;
2716 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002717 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002718 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302719 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002720 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002721 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302723 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2724
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002725 usecase = get_usecase_from_list(adev, uc_id);
2726 if (usecase == NULL) {
2727 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2728 return -EINVAL;
2729 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002731 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002732 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002733 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002734 (usecase->type == ICC_CALL) ||
2735 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302736 if(usecase->stream.out == NULL) {
2737 ALOGE("%s: stream.out is NULL", __func__);
2738 return -EINVAL;
2739 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002740 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002741 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2742 uc_id);
2743 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2744 uc_id);
2745 } else {
2746 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302747 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002748 in_snd_device = platform_get_input_snd_device(adev->platform,
2749 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302750 &usecase->stream.out->device_list,
2751 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002752 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002753 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302754 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302755 if (usecase->stream.inout == NULL) {
2756 ALOGE("%s: stream.inout is NULL", __func__);
2757 return -EINVAL;
2758 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302760 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2761 stream_out.format = usecase->stream.inout->out_config.format;
2762 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302763 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002764 assign_devices(&usecase->device_list,
2765 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302766 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2767 if (usecase->stream.inout == NULL) {
2768 ALOGE("%s: stream.inout is NULL", __func__);
2769 return -EINVAL;
2770 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302771 struct listnode out_devices;
2772 list_init(&out_devices);
2773 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2774 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002775 assign_devices(&usecase->device_list,
2776 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002777 } else {
2778 /*
2779 * If the voice call is active, use the sound devices of voice call usecase
2780 * so that it would not result any device switch. All the usecases will
2781 * be switched to new device when select_devices() is called for voice call
2782 * usecase. This is to avoid switching devices for voice call when
2783 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002784 * choose voice call device only if the use case device is
2785 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002786 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002787 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002788 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002789 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2791 is_codec_backend_out_device_type(&usecase->device_list)) ||
2792 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2793 is_codec_backend_in_device_type(&usecase->device_list)) ||
2794 is_single_device_type_equal(&vc_usecase->device_list,
2795 AUDIO_DEVICE_OUT_HEARING_AID) ||
2796 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002797 AUDIO_DEVICE_IN_VOICE_CALL) ||
2798 (is_single_device_type_equal(&usecase->device_list,
2799 AUDIO_DEVICE_IN_USB_HEADSET) &&
2800 is_single_device_type_equal(&vc_usecase->device_list,
2801 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002802 in_snd_device = vc_usecase->in_snd_device;
2803 out_snd_device = vc_usecase->out_snd_device;
2804 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002805 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002806 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002807 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002808 if ((voip_usecase != NULL) &&
2809 (usecase->type == PCM_PLAYBACK) &&
2810 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002811 out_snd_device_backend_match = platform_check_backends_match(
2812 voip_usecase->out_snd_device,
2813 platform_get_output_snd_device(
2814 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302815 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002816 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002817 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2818 (is_codec_backend_out_device_type(&usecase->device_list) ||
2819 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002820 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002821 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002822 in_snd_device = voip_usecase->in_snd_device;
2823 out_snd_device = voip_usecase->out_snd_device;
2824 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002825 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002826 hfp_ucid = audio_extn_hfp_get_usecase();
2827 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002828 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002829 in_snd_device = hfp_usecase->in_snd_device;
2830 out_snd_device = hfp_usecase->out_snd_device;
2831 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002832 }
2833 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302834 if (usecase->stream.out == NULL) {
2835 ALOGE("%s: stream.out is NULL", __func__);
2836 return -EINVAL;
2837 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002838 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002839 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002840 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002841 struct stream_out *voip_out = adev->primary_output;
2842 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002843 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002844 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2845 else
2846 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302847 usecase->stream.out,
2848 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002849 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002850
Eric Laurent637e2d42018-11-15 12:24:31 -08002851 if (voip_usecase)
2852 voip_out = voip_usecase->stream.out;
2853
2854 if (usecase->stream.out == voip_out && voip_in != NULL)
2855 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002857 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302858 if (usecase->stream.in == NULL) {
2859 ALOGE("%s: stream.in is NULL", __func__);
2860 return -EINVAL;
2861 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002862 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002863 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002864 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002865 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002866 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002867 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002868
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002869 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002870 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002871 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2872 USECASE_AUDIO_PLAYBACK_VOIP);
2873
Carter Hsu2e429db2019-05-14 18:50:52 +08002874 usecase->stream.in->enable_ec_port = false;
2875
Zhou Song62ea0282020-03-22 19:53:01 +08002876 bool is_ha_usecase = adev->ha_proxy_enable ?
2877 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2878 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2879 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002880 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002881 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002882 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002883 } else if (adev->primary_output &&
2884 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002885 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002886 } else {
2887 /* forcing speaker o/p device to get matching i/p pair
2888 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002889 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002890 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002891 priority_in = voip_in;
2892 } else {
2893 /* get the input with the highest priority source*/
2894 priority_in = get_priority_input(adev);
2895
2896 if (!priority_in)
2897 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002898 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002899 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2900 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2901 }
2902 else
2903 in_snd_device = platform_get_input_snd_device(adev->platform,
2904 priority_in,
2905 &out_devices,
2906 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002907 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002908 }
2909 }
2910
2911 if (out_snd_device == usecase->out_snd_device &&
2912 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302913
2914 if (!force_device_switch(usecase))
2915 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 }
2917
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002918 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002919 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002920 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002921 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2922 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302923 }
2924
Aalique Grahame22e49102018-12-18 14:23:57 -08002925 if (out_snd_device != SND_DEVICE_NONE &&
2926 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2927 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2928 __func__,
2929 use_case_table[uc_id],
2930 adev->last_logged_snd_device[uc_id][0],
2931 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2932 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2933 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2934 -1,
2935 out_snd_device,
2936 platform_get_snd_device_name(out_snd_device),
2937 platform_get_snd_device_acdb_id(out_snd_device));
2938 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2939 }
2940 if (in_snd_device != SND_DEVICE_NONE &&
2941 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2942 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2943 __func__,
2944 use_case_table[uc_id],
2945 adev->last_logged_snd_device[uc_id][1],
2946 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2947 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2948 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2949 -1,
2950 in_snd_device,
2951 platform_get_snd_device_name(in_snd_device),
2952 platform_get_snd_device_acdb_id(in_snd_device));
2953 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2954 }
2955
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 /*
2958 * Limitation: While in call, to do a device switch we need to disable
2959 * and enable both RX and TX devices though one of them is same as current
2960 * device.
2961 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002962 if ((usecase->type == VOICE_CALL) &&
2963 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2964 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002965 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002966 }
2967
2968 if (((usecase->type == VOICE_CALL) ||
2969 (usecase->type == VOIP_CALL)) &&
2970 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2971 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302972 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002973 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002974 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002975
2976 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302977 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002978 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002979 }
2980
Aalique Grahame22e49102018-12-18 14:23:57 -08002981 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2982 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002983 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302984 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002985 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2986 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2987 else
2988 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302989 }
2990
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002991 /* Disable current sound devices */
2992 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002993 disable_audio_route(adev, usecase);
2994 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 }
2996
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002997 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002998 disable_audio_route(adev, usecase);
2999 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 }
3001
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003002 /* Applicable only on the targets that has external modem.
3003 * New device information should be sent to modem before enabling
3004 * the devices to reduce in-call device switch time.
3005 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003006 if ((usecase->type == VOICE_CALL) &&
3007 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3008 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003009 status = platform_switch_voice_call_enable_device_config(adev->platform,
3010 out_snd_device,
3011 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003012 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003013
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003014 /* Enable new sound devices */
3015 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003016 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303017 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303018 if (platform_check_codec_asrc_support(adev->platform))
3019 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003020 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003021 /* Enable haptics device for haptic usecase */
3022 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3023 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 }
3025
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003026 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303027 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003028 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003029 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003030
Avinash Vaish71a8b972014-07-24 15:36:33 +05303031 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003032 status = platform_switch_voice_call_device_post(adev->platform,
3033 out_snd_device,
3034 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05303035 enable_audio_route_for_voice_usecases(adev, usecase);
3036 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003037
sangwoo170731f2013-06-08 15:36:36 +09003038 usecase->in_snd_device = in_snd_device;
3039 usecase->out_snd_device = out_snd_device;
3040
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303041 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3042 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303043 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003044 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003045 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003046 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3047 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3048 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3049 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3050 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3051 /*
3052 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3053 * configured device sample rate, if not update the COPP rate to be equal to the
3054 * device sample rate, else open COPP at stream sample rate
3055 */
3056 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3057 usecase->stream.out->sample_rate,
3058 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303059 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303060 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3061 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303062 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003063 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3064 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3065 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3066 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003067 }
3068 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003069
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003070 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003071
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003072 /* If input stream is already running then effect needs to be
3073 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003074 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003075 check_and_enable_effect(adev);
3076
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003077 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003078 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303079 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003080 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3081
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003082 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303083 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003084 voice_extn_compress_voip_is_started(adev))
3085 voice_set_sidetone(adev, out_snd_device, true);
3086 }
3087
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003088 /* Applicable only on the targets that has external modem.
3089 * Enable device command should be sent to modem only after
3090 * enabling voice call mixer controls
3091 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003092 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003093 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3094 out_snd_device,
3095 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303096
3097 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003098 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303099 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003100 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303101 if (is_bt_soc_on(adev) == false){
3102 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003103 if (in->pcm != NULL)
3104 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303105 }
3106 }
3107 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3108 && usecase->stream.out->started) {
3109 if (is_bt_soc_on(adev) == false) {
3110 ALOGD("BT SCO/A2DP disconnected while in connection");
3111 out_standby_l(&usecase->stream.out->stream.common);
3112 }
3113 }
3114 } else if ((usecase->stream.out != NULL) &&
3115 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303116 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3117 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003118 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303119 usecase->stream.out->started) {
3120 if (is_bt_soc_on(adev) == false) {
3121 ALOGD("BT SCO/A2dp disconnected while in connection");
3122 out_standby_l(&usecase->stream.out->stream.common);
3123 }
3124 }
3125 }
3126
Yung Ti Su70cb8242018-06-22 17:38:47 +08003127 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003128 struct stream_out *voip_out = voip_usecase->stream.out;
3129 audio_extn_utils_send_app_type_gain(adev,
3130 voip_out->app_type_cfg.app_type,
3131 &voip_out->app_type_cfg.gain[0]);
3132 }
3133
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003134 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 return status;
3137}
3138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139static int stop_input_stream(struct stream_in *in)
3140{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303141 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303143
3144 if (in == NULL) {
3145 ALOGE("%s: stream_in ptr is NULL", __func__);
3146 return -EINVAL;
3147 }
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003150 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151
Eric Laurent994a6932013-07-17 11:51:42 -07003152 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003153 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 uc_info = get_usecase_from_list(adev, in->usecase);
3155 if (uc_info == NULL) {
3156 ALOGE("%s: Could not find the usecase (%d) in the list",
3157 __func__, in->usecase);
3158 return -EINVAL;
3159 }
3160
Carter Hsu2e429db2019-05-14 18:50:52 +08003161 priority_in = get_priority_input(adev);
3162
Derek Chenea197282019-01-07 17:35:01 -08003163 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3164 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003165
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003166 /* Close in-call recording streams */
3167 voice_check_and_stop_incall_rec_usecase(adev, in);
3168
Eric Laurent150dbfe2013-02-27 14:31:02 -08003169 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003170 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003171
3172 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003173 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003175 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303176 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3177
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003178 list_remove(&uc_info->list);
3179 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180
Carter Hsu2e429db2019-05-14 18:50:52 +08003181 if (priority_in == in) {
3182 priority_in = get_priority_input(adev);
3183 if (priority_in)
3184 select_devices(adev, priority_in->usecase);
3185 }
3186
Vatsal Buchac09ae062018-11-14 13:25:08 +05303187 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003188 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 return ret;
3190}
3191
3192int start_input_stream(struct stream_in *in)
3193{
3194 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003195 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303197
3198 if (in == NULL) {
3199 ALOGE("%s: stream_in ptr is NULL", __func__);
3200 return -EINVAL;
3201 }
3202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003204 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003205 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206
Mingming Yin2664a5b2015-09-03 10:53:11 -07003207 if (get_usecase_from_list(adev, usecase) == NULL)
3208 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303209 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3210 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003211
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303212 if (CARD_STATUS_OFFLINE == in->card_status||
3213 CARD_STATUS_OFFLINE == adev->card_status) {
3214 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303215 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303216 goto error_config;
3217 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303218
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003219 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303220 if (!adev->bt_sco_on) {
3221 ALOGE("%s: SCO profile is not ready, return error", __func__);
3222 ret = -EIO;
3223 goto error_config;
3224 }
3225 }
3226
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003227 /* Check if source matches incall recording usecase criteria */
3228 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3229 if (ret)
3230 goto error_config;
3231 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003232 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3233
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303234 if (audio_extn_cin_attached_usecase(in))
3235 audio_extn_cin_acquire_usecase(in);
3236
Mingming Yin2664a5b2015-09-03 10:53:11 -07003237 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3238 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3239 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003240 ret = -EINVAL;
3241 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003242 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003243
Eric Laurentb23d5282013-05-14 15:27:20 -07003244 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 if (in->pcm_device_id < 0) {
3246 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3247 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003248 ret = -EINVAL;
3249 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003253
3254 if (!uc_info) {
3255 ret = -ENOMEM;
3256 goto error_config;
3257 }
3258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 uc_info->id = in->usecase;
3260 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003261 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003262 list_init(&uc_info->device_list);
3263 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003264 uc_info->in_snd_device = SND_DEVICE_NONE;
3265 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003267 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003268 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303269 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3270 adev->perf_lock_opts,
3271 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003272 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273
Derek Chenea197282019-01-07 17:35:01 -08003274 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3275 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003276
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303277 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3278
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303279 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303280 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303281 if (ret)
3282 goto error_open;
3283 else
3284 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003285 }
3286
Haynes Mathew George16081042017-05-31 17:16:49 -07003287 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003288 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003289 ALOGE("%s: pcm stream not ready", __func__);
3290 goto error_open;
3291 }
3292 ret = pcm_start(in->pcm);
3293 if (ret < 0) {
3294 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3295 goto error_open;
3296 }
3297 } else {
3298 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3299 unsigned int pcm_open_retry_count = 0;
3300
Zhou Song62ea0282020-03-22 19:53:01 +08003301 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3302 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003303 flags |= PCM_MMAP | PCM_NOIRQ;
3304 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3305 } else if (in->realtime) {
3306 flags |= PCM_MMAP | PCM_NOIRQ;
3307 }
3308
Garmond Leunge2433c32017-09-28 21:51:22 -07003309 if (audio_extn_ffv_get_stream() == in) {
3310 ALOGD("%s: ffv stream, update pcm config", __func__);
3311 audio_extn_ffv_update_pcm_config(&config);
3312 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003313 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3314 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3315
3316 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003317 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003318 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003319 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003320 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303321 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303322 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3323 adev->card_status = CARD_STATUS_OFFLINE;
3324 in->card_status = CARD_STATUS_OFFLINE;
3325 ret = -EIO;
3326 goto error_open;
3327 }
3328
Haynes Mathew George16081042017-05-31 17:16:49 -07003329 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3330 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3331 if (in->pcm != NULL) {
3332 pcm_close(in->pcm);
3333 in->pcm = NULL;
3334 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003335 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003336 ret = -EIO;
3337 goto error_open;
3338 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003339 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003340 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3341 continue;
3342 }
3343 break;
3344 }
3345
3346 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003347 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003348 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003349 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003350 if (ret < 0) {
3351 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3352 pcm_close(in->pcm);
3353 in->pcm = NULL;
3354 goto error_open;
3355 }
3356 register_in_stream(in);
3357 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003358 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003359 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003360 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003361 if (ret < 0) {
3362 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003363 pcm_close(in->pcm);
3364 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003365 goto error_open;
3366 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003367 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003368 }
3369
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003370 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003371 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3372 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003373
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003374 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303375 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3376
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303377done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003378 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303379 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303380 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303381 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003382 return ret;
3383
3384error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003385 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303386 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003388
Eric Laurentc8400632013-02-14 19:04:54 -08003389error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003390 if (audio_extn_cin_attached_usecase(in))
3391 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303392 /*
3393 * sleep 50ms to allow sufficient time for kernel
3394 * drivers to recover incases like SSR.
3395 */
3396 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003397 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303398 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003399 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400}
3401
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003402void lock_input_stream(struct stream_in *in)
3403{
3404 pthread_mutex_lock(&in->pre_lock);
3405 pthread_mutex_lock(&in->lock);
3406 pthread_mutex_unlock(&in->pre_lock);
3407}
3408
3409void lock_output_stream(struct stream_out *out)
3410{
3411 pthread_mutex_lock(&out->pre_lock);
3412 pthread_mutex_lock(&out->lock);
3413 pthread_mutex_unlock(&out->pre_lock);
3414}
3415
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416/* must be called with out->lock locked */
3417static int send_offload_cmd_l(struct stream_out* out, int command)
3418{
3419 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3420
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003421 if (!cmd) {
3422 ALOGE("failed to allocate mem for command 0x%x", command);
3423 return -ENOMEM;
3424 }
3425
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426 ALOGVV("%s %d", __func__, command);
3427
3428 cmd->cmd = command;
3429 list_add_tail(&out->offload_cmd_list, &cmd->node);
3430 pthread_cond_signal(&out->offload_cond);
3431 return 0;
3432}
3433
Weiyin Jiang280ea742020-09-08 20:28:22 +08003434/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435static void stop_compressed_output_l(struct stream_out *out)
3436{
3437 out->offload_state = OFFLOAD_STATE_IDLE;
3438 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003439 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440 if (out->compr != NULL) {
3441 compress_stop(out->compr);
3442 while (out->offload_thread_blocked) {
3443 pthread_cond_wait(&out->cond, &out->lock);
3444 }
3445 }
3446}
3447
Varun Balaraje49253e2017-07-06 19:48:56 +05303448bool is_interactive_usecase(audio_usecase_t uc_id)
3449{
3450 unsigned int i;
3451 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3452 if (uc_id == interactive_usecases[i])
3453 return true;
3454 }
3455 return false;
3456}
3457
3458static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3459{
3460 audio_usecase_t ret_uc = USECASE_INVALID;
3461 unsigned int intract_uc_index;
3462 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3463
3464 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3465 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3466 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3467 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3468 ret_uc = interactive_usecases[intract_uc_index];
3469 break;
3470 }
3471 }
3472
3473 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3474 return ret_uc;
3475}
3476
3477static void free_interactive_usecase(struct audio_device *adev,
3478 audio_usecase_t uc_id)
3479{
3480 unsigned int interact_uc_index;
3481 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3482
3483 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3484 if (interactive_usecases[interact_uc_index] == uc_id) {
3485 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3486 break;
3487 }
3488 }
3489 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3490}
3491
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003492bool is_offload_usecase(audio_usecase_t uc_id)
3493{
3494 unsigned int i;
3495 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3496 if (uc_id == offload_usecases[i])
3497 return true;
3498 }
3499 return false;
3500}
3501
Dhananjay Kumarac341582017-02-23 23:42:25 +05303502static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003503{
vivek mehta446c3962015-09-14 10:57:35 -07003504 audio_usecase_t ret_uc = USECASE_INVALID;
3505 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003506 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003507 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303508 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003509 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3510 else
3511 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003512
vivek mehta446c3962015-09-14 10:57:35 -07003513 pthread_mutex_lock(&adev->lock);
3514 if (get_usecase_from_list(adev, ret_uc) != NULL)
3515 ret_uc = USECASE_INVALID;
3516 pthread_mutex_unlock(&adev->lock);
3517
3518 return ret_uc;
3519 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003520
3521 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003522 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3523 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3524 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3525 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003526 break;
3527 }
3528 }
vivek mehta446c3962015-09-14 10:57:35 -07003529
3530 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3531 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003532}
3533
3534static void free_offload_usecase(struct audio_device *adev,
3535 audio_usecase_t uc_id)
3536{
vivek mehta446c3962015-09-14 10:57:35 -07003537 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003538 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003539
3540 if (!adev->multi_offload_enable)
3541 return;
3542
3543 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3544 if (offload_usecases[offload_uc_index] == uc_id) {
3545 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003546 break;
3547 }
3548 }
3549 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3550}
3551
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552static void *offload_thread_loop(void *context)
3553{
3554 struct stream_out *out = (struct stream_out *) context;
3555 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003556 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003559 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3561
3562 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003563 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003564 out->offload_state = OFFLOAD_STATE_IDLE;
3565 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003566 for (;;) {
3567 struct offload_cmd *cmd = NULL;
3568 stream_callback_event_t event;
3569 bool send_callback = false;
3570
3571 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3572 __func__, list_empty(&out->offload_cmd_list),
3573 out->offload_state);
3574 if (list_empty(&out->offload_cmd_list)) {
3575 ALOGV("%s SLEEPING", __func__);
3576 pthread_cond_wait(&out->offload_cond, &out->lock);
3577 ALOGV("%s RUNNING", __func__);
3578 continue;
3579 }
3580
3581 item = list_head(&out->offload_cmd_list);
3582 cmd = node_to_item(item, struct offload_cmd, node);
3583 list_remove(item);
3584
3585 ALOGVV("%s STATE %d CMD %d out->compr %p",
3586 __func__, out->offload_state, cmd->cmd, out->compr);
3587
3588 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3589 free(cmd);
3590 break;
3591 }
3592
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003593 // allow OFFLOAD_CMD_ERROR reporting during standby
3594 // this is needed to handle failures during compress_open
3595 // Note however that on a pause timeout, the stream is closed
3596 // and no offload usecase will be active. Therefore this
3597 // special case is needed for compress_open failures alone
3598 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3599 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003600 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003601 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003602 pthread_cond_signal(&out->cond);
3603 continue;
3604 }
3605 out->offload_thread_blocked = true;
3606 pthread_mutex_unlock(&out->lock);
3607 send_callback = false;
3608 switch(cmd->cmd) {
3609 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003610 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003612 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003613 send_callback = true;
3614 event = STREAM_CBK_EVENT_WRITE_READY;
3615 break;
3616 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003617 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303618 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003619 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303620 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003621 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303622 if (ret < 0)
3623 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303624 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303625 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003626 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003627 else
3628 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003629 if (-ENETRESET != ret && !(-EINTR == ret &&
3630 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303631 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303632 pthread_mutex_lock(&out->lock);
3633 out->send_new_metadata = 1;
3634 out->send_next_track_params = true;
3635 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303636 event = STREAM_CBK_EVENT_DRAIN_READY;
3637 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3638 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303639 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003640 break;
3641 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003642 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003643 ret = compress_drain(out->compr);
3644 ALOGD("copl(%p):out of compress_drain", out);
3645 // EINTR check avoids drain interruption due to SSR
3646 if (-ENETRESET != ret && !(-EINTR == ret &&
3647 CARD_STATUS_OFFLINE == out->card_status)) {
3648 send_callback = true;
3649 event = STREAM_CBK_EVENT_DRAIN_READY;
3650 } else
3651 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303653 case OFFLOAD_CMD_ERROR:
3654 ALOGD("copl(%p): sending error callback to AF", out);
3655 send_callback = true;
3656 event = STREAM_CBK_EVENT_ERROR;
3657 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658 default:
3659 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3660 break;
3661 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003662 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 out->offload_thread_blocked = false;
3664 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003665 if (send_callback && out->client_callback) {
3666 ALOGVV("%s: sending client_callback event %d", __func__, event);
3667 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003668 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669 free(cmd);
3670 }
3671
3672 pthread_cond_signal(&out->cond);
3673 while (!list_empty(&out->offload_cmd_list)) {
3674 item = list_head(&out->offload_cmd_list);
3675 list_remove(item);
3676 free(node_to_item(item, struct offload_cmd, node));
3677 }
3678 pthread_mutex_unlock(&out->lock);
3679
3680 return NULL;
3681}
3682
3683static int create_offload_callback_thread(struct stream_out *out)
3684{
3685 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3686 list_init(&out->offload_cmd_list);
3687 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3688 offload_thread_loop, out);
3689 return 0;
3690}
3691
3692static int destroy_offload_callback_thread(struct stream_out *out)
3693{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003694 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08003695 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003696 stop_compressed_output_l(out);
3697 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3698
Weiyin Jiang280ea742020-09-08 20:28:22 +08003699 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003700 pthread_mutex_unlock(&out->lock);
3701 pthread_join(out->offload_thread, (void **) NULL);
3702 pthread_cond_destroy(&out->offload_cond);
3703
3704 return 0;
3705}
3706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707static int stop_output_stream(struct stream_out *out)
3708{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303709 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 struct audio_usecase *uc_info;
3711 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003712 bool has_voip_usecase =
3713 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714
Eric Laurent994a6932013-07-17 11:51:42 -07003715 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003716 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 uc_info = get_usecase_from_list(adev, out->usecase);
3718 if (uc_info == NULL) {
3719 ALOGE("%s: Could not find the usecase (%d) in the list",
3720 __func__, out->usecase);
3721 return -EINVAL;
3722 }
3723
Derek Chenea197282019-01-07 17:35:01 -08003724 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3725 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003726
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003727 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303728 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 if (adev->visualizer_stop_output != NULL)
3730 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003731
3732 audio_extn_dts_remove_state_notifier_node(out->usecase);
3733
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003734 if (adev->offload_effects_stop_output != NULL)
3735 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003736 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3737 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3738 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003739 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003740
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003741 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3742 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003743 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003744 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003745
Eric Laurent150dbfe2013-02-27 14:31:02 -08003746 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003747 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003748
3749 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003750 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003751 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3752 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753
Aalique Grahame22e49102018-12-18 14:23:57 -08003754 audio_extn_extspk_update(adev->extspk);
3755
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003756 if (is_offload_usecase(out->usecase)) {
3757 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3758 adev->dsp_bit_width_enforce_mode,
3759 false);
3760 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003761 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003762 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3763 false);
3764
3765 if (ret != 0)
3766 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3767 /* default service interval was successfully updated,
3768 reopen USB backend with new service interval */
3769 ret = 0;
3770 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003771
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003772 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303773 out->started = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08003774 pthread_mutex_lock(&out->latch_lock);
3775 out->muted = false;
3776 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003777 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303778 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003779 ALOGV("Disable passthrough , reset mixer to pcm");
3780 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003781#ifdef AUDIO_GKI_ENABLED
3782 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3783 out->compr_config.codec->reserved[0] = 0;
3784#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003785 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003786#endif
Mingming Yin21854652016-04-13 11:54:02 -07003787 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003788 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3789 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003790
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303791 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003792 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303793 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303794
Manish Dewangan21a850a2017-08-14 12:03:55 +05303795 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003796 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3797 if (ret < 0)
3798 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3799 }
3800
juyuchen2d415992018-11-16 14:15:16 +08003801 /* 1) media + voip output routing to handset must route media back to
3802 speaker when voip stops.
3803 2) trigger voip input to reroute when voip output changes to
3804 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003805 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003806 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003807 struct listnode *node;
3808 struct audio_usecase *usecase;
3809 list_for_each(node, &adev->usecase_list) {
3810 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003811 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303812 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3813 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003814 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003815 continue;
3816
3817 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3818 __func__, usecase->id, use_case_table[usecase->id],
3819 out->usecase, use_case_table[out->usecase]);
3820 select_devices(adev, usecase->id);
3821 }
3822 }
3823
Garmond Leung5fd0b552018-04-17 11:56:12 -07003824 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003825 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 return ret;
3827}
3828
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003829struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3830 unsigned int flags, unsigned int pcm_open_retry_count,
3831 struct pcm_config *config)
3832{
3833 struct pcm* pcm = NULL;
3834
3835 while (1) {
3836 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3837 if (pcm == NULL || !pcm_is_ready(pcm)) {
3838 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3839 if (pcm != NULL) {
3840 pcm_close(pcm);
3841 pcm = NULL;
3842 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003843 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003844 return NULL;
3845
Weiyin Jiang72197252019-10-09 11:49:32 +08003846 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003847 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3848 continue;
3849 }
3850 break;
3851 }
3852
3853 if (pcm_is_ready(pcm)) {
3854 int ret = pcm_prepare(pcm);
3855 if (ret < 0) {
3856 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3857 pcm_close(pcm);
3858 pcm = NULL;
3859 }
3860 }
3861
3862 return pcm;
3863}
3864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865int start_output_stream(struct stream_out *out)
3866{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 struct audio_usecase *uc_info;
3869 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003870 char mixer_ctl_name[128];
3871 struct mixer_ctl *ctl = NULL;
3872 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303873 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003874 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875
Haynes Mathew George380745d2017-10-04 15:27:45 -07003876 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003877 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3878 ret = -EINVAL;
3879 goto error_config;
3880 }
3881
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303883 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003884 get_device_types(&out->device_list), is_haptic_usecase);
3885
3886 bool is_speaker_active = compare_device_type(&out->device_list,
3887 AUDIO_DEVICE_OUT_SPEAKER);
3888 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3889 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303890
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303891 if (CARD_STATUS_OFFLINE == out->card_status ||
3892 CARD_STATUS_OFFLINE == adev->card_status) {
3893 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303894 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003895 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303896 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303897
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003898 //Update incall music usecase to reflect correct voice session
3899 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3900 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3901 if (ret != 0) {
3902 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3903 __func__, ret);
3904 goto error_config;
3905 }
3906 }
3907
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003908 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003909 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003910 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303911 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303912 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003913 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303914 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3915 ret = -EAGAIN;
3916 goto error_config;
3917 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303918 }
3919 }
3920 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003921 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303922 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003923 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303924 //combo usecase just by pass a2dp
3925 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003926 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303927 } else {
3928 ALOGE("%s: SCO profile is not ready, return error", __func__);
3929 ret = -EAGAIN;
3930 goto error_config;
3931 }
3932 }
3933 }
3934
Eric Laurentb23d5282013-05-14 15:27:20 -07003935 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 if (out->pcm_device_id < 0) {
3937 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3938 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003939 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003940 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 }
3942
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003943 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003944 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3945 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003946 if (adev->haptic_pcm_device_id < 0) {
3947 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3948 __func__, adev->haptic_pcm_device_id, out->usecase);
3949 ret = -EINVAL;
3950 goto error_config;
3951 }
3952 }
3953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003955
3956 if (!uc_info) {
3957 ret = -ENOMEM;
3958 goto error_config;
3959 }
3960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 uc_info->id = out->usecase;
3962 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003963 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003964 list_init(&uc_info->device_list);
3965 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003966 uc_info->in_snd_device = SND_DEVICE_NONE;
3967 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003968
3969 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003970 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003971 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3972 /* USB backend is not reopened immediately.
3973 This is eventually done as part of select_devices */
3974 }
3975
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003976 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977
Wei Wangf7ca6c92017-11-21 14:51:20 -08003978 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303979 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3980 adev->perf_lock_opts,
3981 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303982
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003983 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303984 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303985 if (audio_extn_passthru_is_enabled() &&
3986 audio_extn_passthru_is_passthrough_stream(out)) {
3987 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303988 }
3989 }
3990
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003991 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003992 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303993 if (!a2dp_combo) {
3994 check_a2dp_restore_l(adev, out, false);
3995 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003996 struct listnode dev;
3997 list_init(&dev);
3998 assign_devices(&dev, &out->device_list);
3999 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4000 reassign_device_list(&out->device_list,
4001 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004002 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004003 reassign_device_list(&out->device_list,
4004 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304005 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004006 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304007 }
4008 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304009 select_devices(adev, out->usecase);
4010 if (is_a2dp_out_device_type(&out->device_list) &&
4011 !adev->a2dp_started) {
4012 if (is_speaker_active || is_speaker_safe_active) {
4013 struct listnode dev;
4014 list_init(&dev);
4015 assign_devices(&dev, &out->device_list);
4016 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4017 reassign_device_list(&out->device_list,
4018 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4019 else
4020 reassign_device_list(&out->device_list,
4021 AUDIO_DEVICE_OUT_SPEAKER, "");
4022 select_devices(adev, out->usecase);
4023 assign_devices(&out->device_list, &dev);
4024 } else {
4025 ret = -EINVAL;
4026 goto error_open;
4027 }
4028 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304029 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004030
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004031 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4032 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004033 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004034 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004035
Derek Chenea197282019-01-07 17:35:01 -08004036 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4037 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004038
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004039 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4040 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004041
4042 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004043 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004044 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4045 ALOGE("%s: pcm stream not ready", __func__);
4046 goto error_open;
4047 }
4048 ret = pcm_start(out->pcm);
4049 if (ret < 0) {
4050 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4051 goto error_open;
4052 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004053 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004054 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004055 unsigned int flags = PCM_OUT;
4056 unsigned int pcm_open_retry_count = 0;
4057 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4058 flags |= PCM_MMAP | PCM_NOIRQ;
4059 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004060 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004061 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004062 } else
4063 flags |= PCM_MONOTONIC;
4064
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004065 if ((adev->vr_audio_mode_enabled) &&
4066 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4067 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4068 "PCM_Dev %d Topology", out->pcm_device_id);
4069 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4070 if (!ctl) {
4071 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4072 __func__, mixer_ctl_name);
4073 } else {
4074 //if success use ULLPP
4075 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4076 __func__, mixer_ctl_name, out->pcm_device_id);
4077 //There is a still a possibility that some sessions
4078 // that request for FAST|RAW when 3D audio is active
4079 //can go through ULLPP. Ideally we expects apps to
4080 //listen to audio focus and stop concurrent playback
4081 //Also, we will look for mode flag (voice_in_communication)
4082 //before enabling the realtime flag.
4083 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4084 }
4085 }
4086
Surendar Karka91fa3682018-07-02 18:12:12 +05304087 if (out->realtime)
4088 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4089 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4090
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004091 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4092 flags, pcm_open_retry_count,
4093 &(out->config));
4094 if (out->pcm == NULL) {
4095 ret = -EIO;
4096 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004097 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004098
4099 if (is_haptic_usecase) {
4100 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4101 adev->haptic_pcm_device_id,
4102 flags, pcm_open_retry_count,
4103 &(adev->haptics_config));
4104 // failure to open haptics pcm shouldnt stop audio,
4105 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004106
4107 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4108 ALOGD("%s: enable haptic audio synchronization", __func__);
4109 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4110 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004111 }
4112
Surendar Karka91fa3682018-07-02 18:12:12 +05304113 if (!out->realtime)
4114 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304115 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004116
Zhou Song2b8f28f2017-09-11 10:51:38 +08004117 // apply volume for voip playback after path is set up
4118 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4119 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304120 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4121 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304122 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4123 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004124 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4125 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304126 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004127 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004128 /*
4129 * set custom channel map if:
4130 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4131 * 2. custom channel map has been set by client
4132 * else default channel map of FC/FR/FL can always be set to DSP
4133 */
4134 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4135 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4136 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004137 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4138 adev->dsp_bit_width_enforce_mode,
4139 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004141 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004142 out->compr = compress_open(adev->snd_card,
4143 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004144 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004145 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304146 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304147 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4148 adev->card_status = CARD_STATUS_OFFLINE;
4149 out->card_status = CARD_STATUS_OFFLINE;
4150 ret = -EIO;
4151 goto error_open;
4152 }
4153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004154 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004155 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004156 compress_close(out->compr);
4157 out->compr = NULL;
4158 ret = -EIO;
4159 goto error_open;
4160 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304161 /* compress_open sends params of the track, so reset the flag here */
4162 out->is_compr_metadata_avail = false;
4163
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004164 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004165 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004166
Fred Oh3f43e742015-03-04 18:42:34 -08004167 /* Since small bufs uses blocking writes, a write will be blocked
4168 for the default max poll time (20s) in the event of an SSR.
4169 Reduce the poll time to observe and deal with SSR faster.
4170 */
Ashish Jain5106d362016-05-11 19:23:33 +05304171 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004172 compress_set_max_poll_wait(out->compr, 1000);
4173 }
4174
Manish Dewangan69426c82017-01-30 17:35:36 +05304175 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304176 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304177
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004178 audio_extn_dts_create_state_notifier_node(out->usecase);
4179 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4180 popcount(out->channel_mask),
4181 out->playback_started);
4182
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004183#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304184 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004185 audio_extn_dolby_send_ddp_endp_params(adev);
4186#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304187 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4188 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004189 if (adev->visualizer_start_output != NULL)
4190 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4191 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304192 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004193 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004194 }
Derek Chenf13dd492018-11-13 14:53:51 -08004195
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004196 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004197 /* Update cached volume from media to offload/direct stream */
4198 struct listnode *node = NULL;
4199 list_for_each(node, &adev->active_outputs_list) {
4200 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4201 streams_output_ctxt_t,
4202 list);
4203 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4204 out->volume_l = out_ctxt->output->volume_l;
4205 out->volume_r = out_ctxt->output->volume_r;
4206 }
4207 }
4208 out_set_compr_volume(&out->stream,
4209 out->volume_l, out->volume_r);
4210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004212
4213 if (ret == 0) {
4214 register_out_stream(out);
4215 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004216 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4217 ALOGE("%s: pcm stream not ready", __func__);
4218 goto error_open;
4219 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004220 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004221 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004222 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004223 if (ret < 0)
4224 goto error_open;
4225 }
4226 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004227 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304228 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304229 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004230
vivek mehtad15d2bf2019-05-17 13:35:10 -07004231 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4232 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4233 audio_low_latency_hint_start();
4234 }
4235
Manish Dewangan21a850a2017-08-14 12:03:55 +05304236 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004237 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004238 if (ret < 0)
4239 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4240 }
4241
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004242 // consider a scenario where on pause lower layers are tear down.
4243 // so on resume, swap mixer control need to be sent only when
4244 // backend is active, hence rather than sending from enable device
4245 // sending it from start of streamtream
4246
4247 platform_set_swap_channels(adev, true);
4248
Haynes Mathew George380745d2017-10-04 15:27:45 -07004249 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304250 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004251 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004252error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004253 if (adev->haptic_pcm) {
4254 pcm_close(adev->haptic_pcm);
4255 adev->haptic_pcm = NULL;
4256 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004257 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304258 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004260error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304261 /*
4262 * sleep 50ms to allow sufficient time for kernel
4263 * drivers to recover incases like SSR.
4264 */
4265 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004266error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004267 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304268 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004269 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270}
4271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272static int check_input_parameters(uint32_t sample_rate,
4273 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004274 int channel_count,
4275 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004277 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304279 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4280 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4281 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004282 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004283 !audio_extn_compr_cap_format_supported(format) &&
4284 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004285 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004286
Aalique Grahame22e49102018-12-18 14:23:57 -08004287 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4288 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4289 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4290 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4291 return -EINVAL;
4292 }
4293
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004294 switch (channel_count) {
4295 case 1:
4296 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304297 case 3:
4298 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004299 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004300 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304301 case 10:
4302 case 12:
4303 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004304 break;
4305 default:
4306 ret = -EINVAL;
4307 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308
4309 switch (sample_rate) {
4310 case 8000:
4311 case 11025:
4312 case 12000:
4313 case 16000:
4314 case 22050:
4315 case 24000:
4316 case 32000:
4317 case 44100:
4318 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004319 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304320 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004321 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304322 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 break;
4324 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004325 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 }
4327
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004328 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329}
4330
Naresh Tanniru04f71882018-06-26 17:46:22 +05304331
4332/** Add a value in a list if not already present.
4333 * @return true if value was successfully inserted or already present,
4334 * false if the list is full and does not contain the value.
4335 */
4336static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4337 for (size_t i = 0; i < list_length; i++) {
4338 if (list[i] == value) return true; // value is already present
4339 if (list[i] == 0) { // no values in this slot
4340 list[i] = value;
4341 return true; // value inserted
4342 }
4343 }
4344 return false; // could not insert value
4345}
4346
4347/** Add channel_mask in supported_channel_masks if not already present.
4348 * @return true if channel_mask was successfully inserted or already present,
4349 * false if supported_channel_masks is full and does not contain channel_mask.
4350 */
4351static void register_channel_mask(audio_channel_mask_t channel_mask,
4352 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4353 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4354 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4355}
4356
4357/** Add format in supported_formats if not already present.
4358 * @return true if format was successfully inserted or already present,
4359 * false if supported_formats is full and does not contain format.
4360 */
4361static void register_format(audio_format_t format,
4362 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4363 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4364 "%s: stream can not declare supporting its format %x", __func__, format);
4365}
4366/** Add sample_rate in supported_sample_rates if not already present.
4367 * @return true if sample_rate was successfully inserted or already present,
4368 * false if supported_sample_rates is full and does not contain sample_rate.
4369 */
4370static void register_sample_rate(uint32_t sample_rate,
4371 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4372 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4373 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4374}
4375
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004376static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4377{
4378 uint32_t high = num1, low = num2, temp = 0;
4379
4380 if (!num1 || !num2)
4381 return 0;
4382
4383 if (num1 < num2) {
4384 high = num2;
4385 low = num1;
4386 }
4387
4388 while (low != 0) {
4389 temp = low;
4390 low = high % low;
4391 high = temp;
4392 }
4393 return (num1 * num2)/high;
4394}
4395
4396static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4397{
4398 uint32_t remainder = 0;
4399
4400 if (!multiplier)
4401 return num;
4402
4403 remainder = num % multiplier;
4404 if (remainder)
4405 num += (multiplier - remainder);
4406
4407 return num;
4408}
4409
Aalique Grahame22e49102018-12-18 14:23:57 -08004410static size_t get_stream_buffer_size(size_t duration_ms,
4411 uint32_t sample_rate,
4412 audio_format_t format,
4413 int channel_count,
4414 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415{
4416 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004417 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418
Aalique Grahame22e49102018-12-18 14:23:57 -08004419 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004420 if (is_low_latency)
4421 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304422
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004423 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004424 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425
Ralf Herzbd08d632018-09-28 15:50:49 +02004426 /* make sure the size is multiple of 32 bytes and additionally multiple of
4427 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004428 * At 48 kHz mono 16-bit PCM:
4429 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4430 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004431 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004432 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004433 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004434
4435 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436}
4437
Aalique Grahame22e49102018-12-18 14:23:57 -08004438static size_t get_input_buffer_size(uint32_t sample_rate,
4439 audio_format_t format,
4440 int channel_count,
4441 bool is_low_latency)
4442{
4443 /* Don't know if USB HIFI in this context so use true to be conservative */
4444 if (check_input_parameters(sample_rate, format, channel_count,
4445 true /*is_usb_hifi */) != 0)
4446 return 0;
4447
4448 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4449 sample_rate,
4450 format,
4451 channel_count,
4452 is_low_latency);
4453}
4454
Derek Chenf6318be2017-06-12 17:16:24 -04004455size_t get_output_period_size(uint32_t sample_rate,
4456 audio_format_t format,
4457 int channel_count,
4458 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304459{
4460 size_t size = 0;
4461 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4462
4463 if ((duration == 0) || (sample_rate == 0) ||
4464 (bytes_per_sample == 0) || (channel_count == 0)) {
4465 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4466 bytes_per_sample, channel_count);
4467 return -EINVAL;
4468 }
4469
4470 size = (sample_rate *
4471 duration *
4472 bytes_per_sample *
4473 channel_count) / 1000;
4474 /*
4475 * To have same PCM samples for all channels, the buffer size requires to
4476 * be multiple of (number of channels * bytes per sample)
4477 * For writes to succeed, the buffer must be written at address which is multiple of 32
4478 */
4479 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4480
4481 return (size/(channel_count * bytes_per_sample));
4482}
4483
Zhou Song48453a02018-01-10 17:50:59 +08004484static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304485{
4486 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004487 uint64_t written_frames = 0;
4488 uint64_t kernel_frames = 0;
4489 uint64_t dsp_frames = 0;
4490 uint64_t signed_frames = 0;
4491 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304492
4493 /* This adjustment accounts for buffering after app processor.
4494 * It is based on estimated DSP latency per use case, rather than exact.
4495 */
George Gao9ba8a142020-07-23 14:30:03 -07004496 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004497 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304498
Zhou Song48453a02018-01-10 17:50:59 +08004499 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004500 written_frames = out->written /
4501 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4502
Ashish Jain5106d362016-05-11 19:23:33 +05304503 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4504 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4505 * hence only estimate.
4506 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004507 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4508 kernel_frames = kernel_buffer_size /
4509 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304510
Weiyin Jiang4813da12020-05-28 00:37:28 +08004511 if (written_frames >= (kernel_frames + dsp_frames))
4512 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304513
Zhou Song48453a02018-01-10 17:50:59 +08004514 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304515 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004516 if (timestamp != NULL )
4517 *timestamp = out->writeAt;
4518 } else if (timestamp != NULL) {
4519 clock_gettime(CLOCK_MONOTONIC, timestamp);
4520 }
4521 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304522
Weiyin Jiang4813da12020-05-28 00:37:28 +08004523 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4524 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304525
4526 return actual_frames_rendered;
4527}
4528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4530{
4531 struct stream_out *out = (struct stream_out *)stream;
4532
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004533 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004534}
4535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004536static int out_set_sample_rate(struct audio_stream *stream __unused,
4537 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538{
4539 return -ENOSYS;
4540}
4541
4542static size_t out_get_buffer_size(const struct audio_stream *stream)
4543{
4544 struct stream_out *out = (struct stream_out *)stream;
4545
Varun Balaraje49253e2017-07-06 19:48:56 +05304546 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304547 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304548 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304549 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4550 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4551 else
4552 return out->compr_config.fragment_size;
4553 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004554 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304555 else if (is_offload_usecase(out->usecase) &&
4556 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304557 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004558
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004559 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004560 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561}
4562
4563static uint32_t out_get_channels(const struct audio_stream *stream)
4564{
4565 struct stream_out *out = (struct stream_out *)stream;
4566
4567 return out->channel_mask;
4568}
4569
4570static audio_format_t out_get_format(const struct audio_stream *stream)
4571{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004572 struct stream_out *out = (struct stream_out *)stream;
4573
4574 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575}
4576
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004577static int out_set_format(struct audio_stream *stream __unused,
4578 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579{
4580 return -ENOSYS;
4581}
4582
4583static int out_standby(struct audio_stream *stream)
4584{
4585 struct stream_out *out = (struct stream_out *)stream;
4586 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004587 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004588
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304589 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4590 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004592 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004594 if (adev->adm_deregister_stream)
4595 adev->adm_deregister_stream(adev->adm_data, out->handle);
4596
Weiyin Jiang280ea742020-09-08 20:28:22 +08004597 if (is_offload_usecase(out->usecase)) {
4598 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004599 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004600 pthread_mutex_unlock(&out->latch_lock);
4601 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004602
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004603 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004605 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4606 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304607 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004608 pthread_mutex_unlock(&adev->lock);
4609 pthread_mutex_unlock(&out->lock);
4610 ALOGD("VOIP output entered standby");
4611 return 0;
4612 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004613 if (out->pcm) {
4614 pcm_close(out->pcm);
4615 out->pcm = NULL;
4616 }
Meng Wanga09da002020-04-20 12:56:04 +08004617 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4618 if (adev->haptic_pcm) {
4619 pcm_close(adev->haptic_pcm);
4620 adev->haptic_pcm = NULL;
4621 }
4622
4623 if (adev->haptic_buffer != NULL) {
4624 free(adev->haptic_buffer);
4625 adev->haptic_buffer = NULL;
4626 adev->haptic_buffer_size = 0;
4627 }
4628 adev->haptic_pcm_device_id = 0;
4629 }
4630
Haynes Mathew George16081042017-05-31 17:16:49 -07004631 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4632 do_stop = out->playback_started;
4633 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004634
4635 if (out->mmap_shared_memory_fd >= 0) {
4636 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4637 __func__, out->mmap_shared_memory_fd);
4638 close(out->mmap_shared_memory_fd);
4639 out->mmap_shared_memory_fd = -1;
4640 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004641 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004642 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004643 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304644 out->send_next_track_params = false;
4645 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004646 out->gapless_mdata.encoder_delay = 0;
4647 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004648 if (out->compr != NULL) {
4649 compress_close(out->compr);
4650 out->compr = NULL;
4651 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004652 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004653 if (do_stop) {
4654 stop_output_stream(out);
4655 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304656 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004657 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004658 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659 }
4660 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004661 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 return 0;
4663}
4664
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304665static int out_on_error(struct audio_stream *stream)
4666{
4667 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004668 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304669
4670 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004671 // always send CMD_ERROR for offload streams, this
4672 // is needed e.g. when SSR happens within compress_open
4673 // since the stream is active, offload_callback_thread is also active.
4674 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08004675 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004676 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004677 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004678 }
4679 pthread_mutex_unlock(&out->lock);
4680
4681 status = out_standby(&out->stream.common);
4682
4683 lock_output_stream(out);
4684 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004685 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304686 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304687
4688 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4689 ALOGD("Setting previous card status if offline");
4690 out->prev_card_status_offline = true;
4691 }
4692
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304693 pthread_mutex_unlock(&out->lock);
4694
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004695 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304696}
4697
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304698/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004699 * standby implementation without locks, assumes that the callee already
4700 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304701 */
4702int out_standby_l(struct audio_stream *stream)
4703{
4704 struct stream_out *out = (struct stream_out *)stream;
4705 struct audio_device *adev = out->dev;
4706
4707 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4708 stream, out->usecase, use_case_table[out->usecase]);
4709
4710 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004711 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304712 if (adev->adm_deregister_stream)
4713 adev->adm_deregister_stream(adev->adm_data, out->handle);
4714
Weiyin Jiang280ea742020-09-08 20:28:22 +08004715 if (is_offload_usecase(out->usecase)) {
4716 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304717 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004718 pthread_mutex_unlock(&out->latch_lock);
4719 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304720
4721 out->standby = true;
4722 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4723 voice_extn_compress_voip_close_output_stream(stream);
4724 out->started = 0;
4725 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004726 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304727 return 0;
4728 } else if (!is_offload_usecase(out->usecase)) {
4729 if (out->pcm) {
4730 pcm_close(out->pcm);
4731 out->pcm = NULL;
4732 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004733 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4734 if (adev->haptic_pcm) {
4735 pcm_close(adev->haptic_pcm);
4736 adev->haptic_pcm = NULL;
4737 }
4738
4739 if (adev->haptic_buffer != NULL) {
4740 free(adev->haptic_buffer);
4741 adev->haptic_buffer = NULL;
4742 adev->haptic_buffer_size = 0;
4743 }
4744 adev->haptic_pcm_device_id = 0;
4745 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304746 } else {
4747 ALOGD("copl(%p):standby", out);
4748 out->send_next_track_params = false;
4749 out->is_compr_metadata_avail = false;
4750 out->gapless_mdata.encoder_delay = 0;
4751 out->gapless_mdata.encoder_padding = 0;
4752 if (out->compr != NULL) {
4753 compress_close(out->compr);
4754 out->compr = NULL;
4755 }
4756 }
4757 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004758 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304759 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004760 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304761 return 0;
4762}
4763
Aalique Grahame22e49102018-12-18 14:23:57 -08004764static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765{
Aalique Grahame22e49102018-12-18 14:23:57 -08004766 struct stream_out *out = (struct stream_out *)stream;
4767
4768 // We try to get the lock for consistency,
4769 // but it isn't necessary for these variables.
4770 // If we're not in standby, we may be blocked on a write.
4771 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4772 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4773 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4774
Andy Hunga1f48fa2019-07-01 18:14:53 -07004775 char buffer[256]; // for statistics formatting
4776 if (!is_offload_usecase(out->usecase)) {
4777 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4778 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4779 }
4780
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004781 if (out->start_latency_ms.n > 0) {
4782 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4783 dprintf(fd, " Start latency ms: %s\n", buffer);
4784 }
4785
Aalique Grahame22e49102018-12-18 14:23:57 -08004786 if (locked) {
4787 pthread_mutex_unlock(&out->lock);
4788 }
4789
4790 // dump error info
4791 (void)error_log_dump(
4792 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794 return 0;
4795}
4796
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004797static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4798{
4799 int ret = 0;
4800 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004801
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004802 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004803 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004804 return -EINVAL;
4805 }
4806
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304807 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004808
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004809 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4810 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304811 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004812 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004813 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4814 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304815 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004816 }
4817
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004818 ALOGV("%s new encoder delay %u and padding %u", __func__,
4819 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4820
4821 return 0;
4822}
4823
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004824static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4825{
4826 return out == adev->primary_output || out == adev->voice_tx_output;
4827}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004828
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304829// note: this call is safe only if the stream_cb is
4830// removed first in close_output_stream (as is done now).
4831static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4832{
4833 if (!stream || !parms)
4834 return;
4835
4836 struct stream_out *out = (struct stream_out *)stream;
4837 struct audio_device *adev = out->dev;
4838
4839 card_status_t status;
4840 int card;
4841 if (parse_snd_card_status(parms, &card, &status) < 0)
4842 return;
4843
4844 pthread_mutex_lock(&adev->lock);
4845 bool valid_cb = (card == adev->snd_card);
4846 pthread_mutex_unlock(&adev->lock);
4847
4848 if (!valid_cb)
4849 return;
4850
4851 lock_output_stream(out);
4852 if (out->card_status != status)
4853 out->card_status = status;
4854 pthread_mutex_unlock(&out->lock);
4855
4856 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4857 use_case_table[out->usecase],
4858 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4859
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304860 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304861 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304862 if (voice_is_call_state_active(adev) &&
4863 out == adev->primary_output) {
4864 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4865 pthread_mutex_lock(&adev->lock);
4866 voice_stop_call(adev);
4867 adev->mode = AUDIO_MODE_NORMAL;
4868 pthread_mutex_unlock(&adev->lock);
4869 }
4870 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304871 return;
4872}
4873
Kevin Rocardfce19002017-08-07 19:21:36 -07004874static int get_alive_usb_card(struct str_parms* parms) {
4875 int card;
4876 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4877 !audio_extn_usb_alive(card)) {
4878 return card;
4879 }
4880 return -ENODEV;
4881}
4882
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004883int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004884 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004885{
4886 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004888 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004889 bool bypass_a2dp = false;
4890 bool reconfig = false;
4891 unsigned long service_interval = 0;
4892
4893 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004894 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4895
4896 list_init(&new_devices);
4897 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004898
4899 lock_output_stream(out);
4900 pthread_mutex_lock(&adev->lock);
4901
4902 /*
4903 * When HDMI cable is unplugged the music playback is paused and
4904 * the policy manager sends routing=0. But the audioflinger continues
4905 * to write data until standby time (3sec). As the HDMI core is
4906 * turned off, the write gets blocked.
4907 * Avoid this by routing audio to speaker until standby.
4908 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004909 if (is_single_device_type_equal(&out->device_list,
4910 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004911 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004912 !audio_extn_passthru_is_passthrough_stream(out) &&
4913 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004914 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004915 }
4916 /*
4917 * When A2DP is disconnected the
4918 * music playback is paused and the policy manager sends routing=0
4919 * But the audioflinger continues to write data until standby time
4920 * (3sec). As BT is turned off, the write gets blocked.
4921 * Avoid this by routing audio to speaker until standby.
4922 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004923 if (is_a2dp_out_device_type(&out->device_list) &&
4924 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004925 !audio_extn_a2dp_source_is_ready() &&
4926 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004927 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004928 }
4929 /*
4930 * When USB headset is disconnected the music platback paused
4931 * and the policy manager send routing=0. But if the USB is connected
4932 * back before the standby time, AFE is not closed and opened
4933 * when USB is connected back. So routing to speker will guarantee
4934 * AFE reconfiguration and AFE will be opend once USB is connected again
4935 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004936 if (is_usb_out_device_type(&out->device_list) &&
4937 list_empty(&new_devices) &&
4938 !audio_extn_usb_connected(NULL)) {
4939 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4940 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004941 /* To avoid a2dp to sco overlapping / BT device improper state
4942 * check with BT lib about a2dp streaming support before routing
4943 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004944 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004945 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004946 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4947 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004948 //combo usecase just by pass a2dp
4949 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4950 bypass_a2dp = true;
4951 } else {
4952 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4953 /* update device to a2dp and don't route as BT returned error
4954 * However it is still possible a2dp routing called because
4955 * of current active device disconnection (like wired headset)
4956 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004957 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004958 pthread_mutex_unlock(&adev->lock);
4959 pthread_mutex_unlock(&out->lock);
4960 goto error;
4961 }
4962 }
4963 }
4964
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004965 // Workaround: If routing to an non existing usb device, fail gracefully
4966 // The routing request will otherwise block during 10 second
4967 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004968 if (is_usb_out_device_type(&new_devices)) {
4969 struct str_parms *parms =
4970 str_parms_create_str(get_usb_device_address(&new_devices));
4971 if (!parms)
4972 goto error;
4973 if ((card = get_alive_usb_card(parms)) >= 0) {
4974 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4975 pthread_mutex_unlock(&adev->lock);
4976 pthread_mutex_unlock(&out->lock);
4977 str_parms_destroy(parms);
4978 ret = -ENOSYS;
4979 goto error;
4980 }
4981 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004982 }
4983
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004984 // Workaround: If routing to an non existing hdmi device, fail gracefully
4985 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4986 (platform_get_edid_info_v2(adev->platform,
4987 out->extconn.cs.controller,
4988 out->extconn.cs.stream) != 0)) {
4989 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4990 pthread_mutex_unlock(&adev->lock);
4991 pthread_mutex_unlock(&out->lock);
4992 ret = -ENOSYS;
4993 goto error;
4994 }
4995
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004996 /*
4997 * select_devices() call below switches all the usecases on the same
4998 * backend to the new device. Refer to check_usecases_codec_backend() in
4999 * the select_devices(). But how do we undo this?
5000 *
5001 * For example, music playback is active on headset (deep-buffer usecase)
5002 * and if we go to ringtones and select a ringtone, low-latency usecase
5003 * will be started on headset+speaker. As we can't enable headset+speaker
5004 * and headset devices at the same time, select_devices() switches the music
5005 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5006 * So when the ringtone playback is completed, how do we undo the same?
5007 *
5008 * We are relying on the out_set_parameters() call on deep-buffer output,
5009 * once the ringtone playback is ended.
5010 * NOTE: We should not check if the current devices are same as new devices.
5011 * Because select_devices() must be called to switch back the music
5012 * playback to headset.
5013 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005014 if (!list_empty(&new_devices)) {
5015 bool same_dev = compare_devices(&out->device_list, &new_devices);
5016 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017
5018 if (output_drives_call(adev, out)) {
5019 if (!voice_is_call_state_active(adev)) {
5020 if (adev->mode == AUDIO_MODE_IN_CALL) {
5021 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005022 ret = voice_start_call(adev);
5023 }
5024 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005025 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005026 adev->current_call_output = out;
5027 voice_update_devices_for_all_voice_usecases(adev);
5028 }
5029 }
5030
Mingshu Pang971ff702020-09-09 15:28:22 +08005031 if (is_usb_out_device_type(&out->device_list)) {
5032 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5033 audio_extn_usb_set_service_interval(true /*playback*/,
5034 service_interval,
5035 &reconfig);
5036 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5037 }
5038
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005039 if (!out->standby) {
5040 if (!same_dev) {
5041 ALOGV("update routing change");
5042 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5043 adev->perf_lock_opts,
5044 adev->perf_lock_opts_size);
5045 if (adev->adm_on_routing_change)
5046 adev->adm_on_routing_change(adev->adm_data,
5047 out->handle);
5048 }
5049 if (!bypass_a2dp) {
5050 select_devices(adev, out->usecase);
5051 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005052 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5053 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005054 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005055 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005056 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005057 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005058 }
5059
5060 if (!same_dev) {
5061 // on device switch force swap, lower functions will make sure
5062 // to check if swap is allowed or not.
5063 platform_set_swap_channels(adev, true);
5064 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5065 }
Zhou Songd01e7a22020-09-23 22:49:01 +08005066 if (is_offload_usecase(out->usecase) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005067 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005068 pthread_mutex_lock(&out->latch_lock);
5069 if (out->a2dp_compress_mute) {
5070 out->a2dp_compress_mute = false;
5071 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5072 }
5073 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005074 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5075 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5076 }
5077 }
5078 }
5079
5080 pthread_mutex_unlock(&adev->lock);
5081 pthread_mutex_unlock(&out->lock);
5082
5083 /*handles device and call state changes*/
5084 audio_extn_extspk_update(adev->extspk);
5085
5086error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005087 ALOGV("%s: exit: code(%d)", __func__, ret);
5088 return ret;
5089}
5090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5092{
5093 struct stream_out *out = (struct stream_out *)stream;
5094 struct audio_device *adev = out->dev;
5095 struct str_parms *parms;
5096 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005097 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005098 int ext_controller = -1;
5099 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100
sangwoobc677242013-08-08 16:53:43 +09005101 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005102 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305104 if (!parms)
5105 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005106
5107 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5108 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005109 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005110 out->extconn.cs.controller = ext_controller;
5111 out->extconn.cs.stream = ext_stream;
5112 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5113 use_case_table[out->usecase], out->extconn.cs.controller,
5114 out->extconn.cs.stream);
5115 }
5116
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005117 if (out == adev->primary_output) {
5118 pthread_mutex_lock(&adev->lock);
5119 audio_extn_set_parameters(adev, parms);
5120 pthread_mutex_unlock(&adev->lock);
5121 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005122 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005123 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005124 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005125
5126 audio_extn_dts_create_state_notifier_node(out->usecase);
5127 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5128 popcount(out->channel_mask),
5129 out->playback_started);
5130
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005131 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005132 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005133
Surendar Karkaf51b5842018-04-26 11:28:38 +05305134 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5135 sizeof(value));
5136 if (err >= 0) {
5137 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5138 audio_extn_send_dual_mono_mixing_coefficients(out);
5139 }
5140
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305141 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5142 if (err >= 0) {
5143 strlcpy(out->profile, value, sizeof(out->profile));
5144 ALOGV("updating stream profile with value '%s'", out->profile);
5145 lock_output_stream(out);
5146 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5147 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005148 &out->device_list, out->flags,
5149 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305150 out->sample_rate, out->bit_width,
5151 out->channel_mask, out->profile,
5152 &out->app_type_cfg);
5153 pthread_mutex_unlock(&out->lock);
5154 }
5155
Alexy Joseph98988832017-01-13 14:56:59 -08005156 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005157 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5158 // and vendor.audio.hal.output.suspend.supported is set to true
5159 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005160 //check suspend parameter only for low latency and if the property
5161 //is enabled
5162 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5163 ALOGI("%s: got suspend_playback %s", __func__, value);
5164 lock_output_stream(out);
5165 if (!strncmp(value, "false", 5)) {
5166 //suspend_playback=false is supposed to set QOS value back to 75%
5167 //the mixer control sent with value Enable will achieve that
5168 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5169 } else if (!strncmp (value, "true", 4)) {
5170 //suspend_playback=true is supposed to remove QOS value
5171 //resetting the mixer control will set the default value
5172 //for the mixer control which is Disable and this removes the QOS vote
5173 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5174 } else {
5175 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5176 " got %s", __func__, value);
5177 ret = -1;
5178 }
5179
5180 if (ret != 0) {
5181 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5182 __func__, out->pm_qos_mixer_path, ret);
5183 }
5184
5185 pthread_mutex_unlock(&out->lock);
5186 }
5187 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005188
Alexy Joseph98988832017-01-13 14:56:59 -08005189 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305191error:
Eric Laurent994a6932013-07-17 11:51:42 -07005192 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005193 return ret;
5194}
5195
Paul McLeana50b7332018-12-17 08:24:21 -07005196static int in_set_microphone_direction(const struct audio_stream_in *stream,
5197 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005198 struct stream_in *in = (struct stream_in *)stream;
5199
5200 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5201
5202 in->direction = dir;
5203
5204 if (in->standby)
5205 return 0;
5206
5207 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005208}
5209
5210static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005211 struct stream_in *in = (struct stream_in *)stream;
5212
5213 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5214
5215 if (zoom > 1.0 || zoom < -1.0)
5216 return -EINVAL;
5217
5218 in->zoom = zoom;
5219
5220 if (in->standby)
5221 return 0;
5222
5223 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005224}
5225
5226
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005227static bool stream_get_parameter_channels(struct str_parms *query,
5228 struct str_parms *reply,
5229 audio_channel_mask_t *supported_channel_masks) {
5230 int ret = -1;
5231 char value[512];
5232 bool first = true;
5233 size_t i, j;
5234
5235 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5236 ret = 0;
5237 value[0] = '\0';
5238 i = 0;
5239 while (supported_channel_masks[i] != 0) {
5240 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5241 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5242 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305243 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005244
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305245 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005246 first = false;
5247 break;
5248 }
5249 }
5250 i++;
5251 }
5252 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5253 }
5254 return ret == 0;
5255}
5256
5257static bool stream_get_parameter_formats(struct str_parms *query,
5258 struct str_parms *reply,
5259 audio_format_t *supported_formats) {
5260 int ret = -1;
5261 char value[256];
5262 size_t i, j;
5263 bool first = true;
5264
5265 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5266 ret = 0;
5267 value[0] = '\0';
5268 i = 0;
5269 while (supported_formats[i] != 0) {
5270 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5271 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5272 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305273 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005274 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305275 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005276 first = false;
5277 break;
5278 }
5279 }
5280 i++;
5281 }
5282 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5283 }
5284 return ret == 0;
5285}
5286
5287static bool stream_get_parameter_rates(struct str_parms *query,
5288 struct str_parms *reply,
5289 uint32_t *supported_sample_rates) {
5290
5291 int i;
5292 char value[256];
5293 int ret = -1;
5294 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5295 ret = 0;
5296 value[0] = '\0';
5297 i=0;
5298 int cursor = 0;
5299 while (supported_sample_rates[i]) {
5300 int avail = sizeof(value) - cursor;
5301 ret = snprintf(value + cursor, avail, "%s%d",
5302 cursor > 0 ? "|" : "",
5303 supported_sample_rates[i]);
5304 if (ret < 0 || ret >= avail) {
5305 // if cursor is at the last element of the array
5306 // overwrite with \0 is duplicate work as
5307 // snprintf already put a \0 in place.
5308 // else
5309 // we had space to write the '|' at value[cursor]
5310 // (which will be overwritten) or no space to fill
5311 // the first element (=> cursor == 0)
5312 value[cursor] = '\0';
5313 break;
5314 }
5315 cursor += ret;
5316 ++i;
5317 }
5318 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5319 value);
5320 }
5321 return ret >= 0;
5322}
5323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5325{
5326 struct stream_out *out = (struct stream_out *)stream;
5327 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005328 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005329 char value[256];
5330 struct str_parms *reply = str_parms_create();
5331 size_t i, j;
5332 int ret;
5333 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005334
5335 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005336 if (reply) {
5337 str_parms_destroy(reply);
5338 }
5339 if (query) {
5340 str_parms_destroy(query);
5341 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005342 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5343 return NULL;
5344 }
5345
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005346 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5348 if (ret >= 0) {
5349 value[0] = '\0';
5350 i = 0;
5351 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005352 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5353 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005354 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005355 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005357 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358 first = false;
5359 break;
5360 }
5361 }
5362 i++;
5363 }
5364 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5365 str = str_parms_to_str(reply);
5366 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005367 voice_extn_out_get_parameters(out, query, reply);
5368 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005370
Alexy Joseph62142aa2015-11-16 15:10:34 -08005371
5372 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5373 if (ret >= 0) {
5374 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305375 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5376 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005377 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305378 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005379 } else {
5380 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305381 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005382 }
5383 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005384 if (str)
5385 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005386 str = str_parms_to_str(reply);
5387 }
5388
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005389 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5390 if (ret >= 0) {
5391 value[0] = '\0';
5392 i = 0;
5393 first = true;
5394 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005395 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5396 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005397 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005398 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005399 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005400 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005401 first = false;
5402 break;
5403 }
5404 }
5405 i++;
5406 }
5407 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005408 if (str)
5409 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005410 str = str_parms_to_str(reply);
5411 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005412
5413 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5414 if (ret >= 0) {
5415 value[0] = '\0';
5416 i = 0;
5417 first = true;
5418 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005419 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5420 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005421 if (!first) {
5422 strlcat(value, "|", sizeof(value));
5423 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005424 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005425 first = false;
5426 break;
5427 }
5428 }
5429 i++;
5430 }
5431 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5432 if (str)
5433 free(str);
5434 str = str_parms_to_str(reply);
5435 }
5436
Alexy Joseph98988832017-01-13 14:56:59 -08005437 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5438 //only low latency track supports suspend_resume
5439 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005440 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005441 if (str)
5442 free(str);
5443 str = str_parms_to_str(reply);
5444 }
5445
5446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005447 str_parms_destroy(query);
5448 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005449 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450 return str;
5451}
5452
5453static uint32_t out_get_latency(const struct audio_stream_out *stream)
5454{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005455 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005457 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458
Alexy Josephaa54c872014-12-03 02:46:47 -08005459 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305460 lock_output_stream(out);
5461 latency = audio_extn_utils_compress_get_dsp_latency(out);
5462 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005463 } else if ((out->realtime) ||
5464 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005465 // since the buffer won't be filled up faster than realtime,
5466 // return a smaller number
5467 if (out->config.rate)
5468 period_ms = (out->af_period_multiplier * out->config.period_size *
5469 1000) / (out->config.rate);
5470 else
5471 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005472 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005473 } else {
5474 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005475 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005476 }
5477
Zhou Songd2537a02020-06-11 22:04:46 +08005478 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005479 latency += audio_extn_a2dp_get_encoder_latency();
5480
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305481 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005482 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483}
5484
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305485static float AmpToDb(float amplification)
5486{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305487 float db = DSD_VOLUME_MIN_DB;
5488 if (amplification > 0) {
5489 db = 20 * log10(amplification);
5490 if(db < DSD_VOLUME_MIN_DB)
5491 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305492 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305493 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305494}
5495
Arun Mirpuri5d170872019-03-26 13:21:31 -07005496static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5497 float right)
5498{
5499 struct stream_out *out = (struct stream_out *)stream;
5500 long volume = 0;
5501 char mixer_ctl_name[128] = "";
5502 struct audio_device *adev = out->dev;
5503 struct mixer_ctl *ctl = NULL;
5504 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5505 PCM_PLAYBACK);
5506
5507 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5508 "Playback %d Volume", pcm_device_id);
5509 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5510 if (!ctl) {
5511 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5512 __func__, mixer_ctl_name);
5513 return -EINVAL;
5514 }
5515 if (left != right)
5516 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5517 __func__, left, right);
5518 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5519 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5520 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5521 __func__, mixer_ctl_name, volume);
5522 return -EINVAL;
5523 }
5524 return 0;
5525}
5526
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305527static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5528 float right)
5529{
5530 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305531 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305532 char mixer_ctl_name[128];
5533 struct audio_device *adev = out->dev;
5534 struct mixer_ctl *ctl;
5535 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5536 PCM_PLAYBACK);
5537
5538 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5539 "Compress Playback %d Volume", pcm_device_id);
5540 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5541 if (!ctl) {
5542 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5543 __func__, mixer_ctl_name);
5544 return -EINVAL;
5545 }
5546 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5547 __func__, mixer_ctl_name, left, right);
5548 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5549 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5550 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5551
5552 return 0;
5553}
5554
Zhou Song2b8f28f2017-09-11 10:51:38 +08005555static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5556 float right)
5557{
5558 struct stream_out *out = (struct stream_out *)stream;
5559 char mixer_ctl_name[] = "App Type Gain";
5560 struct audio_device *adev = out->dev;
5561 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305562 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005563
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005564 if (!is_valid_volume(left, right)) {
5565 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5566 __func__, left, right);
5567 return -EINVAL;
5568 }
5569
Zhou Song2b8f28f2017-09-11 10:51:38 +08005570 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5571 if (!ctl) {
5572 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5573 __func__, mixer_ctl_name);
5574 return -EINVAL;
5575 }
5576
5577 set_values[0] = 0; //0: Rx Session 1:Tx Session
5578 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305579 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5580 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005581
5582 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5583 return 0;
5584}
5585
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305586static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5587 float right)
5588{
5589 struct stream_out *out = (struct stream_out *)stream;
5590 /* Volume control for pcm playback */
5591 if (left != right) {
5592 return -EINVAL;
5593 } else {
5594 char mixer_ctl_name[128];
5595 struct audio_device *adev = out->dev;
5596 struct mixer_ctl *ctl;
5597 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5598 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5599 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5600 if (!ctl) {
5601 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5602 return -EINVAL;
5603 }
5604
5605 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5606 int ret = mixer_ctl_set_value(ctl, 0, volume);
5607 if (ret < 0) {
5608 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5609 return -EINVAL;
5610 }
5611
5612 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5613
5614 return 0;
5615 }
5616}
5617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005618static int out_set_volume(struct audio_stream_out *stream, float left,
5619 float right)
5620{
Eric Laurenta9024de2013-04-04 09:19:12 -07005621 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005622 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305623 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005624
Arun Mirpuri5d170872019-03-26 13:21:31 -07005625 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005626 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5627 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiang280ea742020-09-08 20:28:22 +08005628 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005629 out->muted = (left == 0.0f);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005630 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005631 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005632 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305633 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005634 /*
5635 * Set mute or umute on HDMI passthrough stream.
5636 * Only take left channel into account.
5637 * Mute is 0 and unmute 1
5638 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305639 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305640 } else if (out->format == AUDIO_FORMAT_DSD){
5641 char mixer_ctl_name[128] = "DSD Volume";
5642 struct audio_device *adev = out->dev;
5643 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5644
5645 if (!ctl) {
5646 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5647 __func__, mixer_ctl_name);
5648 return -EINVAL;
5649 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305650 volume[0] = (long)(AmpToDb(left));
5651 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305652 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5653 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005654 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005655 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005656 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5657 struct listnode *node = NULL;
5658 list_for_each(node, &adev->active_outputs_list) {
5659 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5660 streams_output_ctxt_t,
5661 list);
5662 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5663 out->volume_l = out_ctxt->output->volume_l;
5664 out->volume_r = out_ctxt->output->volume_r;
5665 }
5666 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005667 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005668 if (!out->a2dp_compress_mute) {
5669 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5670 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005671 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005672 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005673 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005674 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005675 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305676 if (!out->a2dp_compress_mute)
5677 ret = out_set_compr_volume(stream, left, right);
5678 out->volume_l = left;
5679 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005680 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305681 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005682 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005683 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005684 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5685 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5686 if (!out->standby) {
5687 audio_extn_utils_send_app_type_gain(out->dev,
5688 out->app_type_cfg.app_type,
5689 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005690 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005691 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005692 out->volume_l = left;
5693 out->volume_r = right;
5694 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005695 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5696 ALOGV("%s: MMAP set volume called", __func__);
5697 if (!out->standby)
5698 ret = out_set_mmap_volume(stream, left, right);
5699 out->volume_l = left;
5700 out->volume_r = right;
5701 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305702 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305703 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5704 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305705 /* Volume control for pcm playback */
5706 if (!out->standby)
5707 ret = out_set_pcm_volume(stream, left, right);
5708 else
5709 out->apply_volume = true;
5710
5711 out->volume_l = left;
5712 out->volume_r = right;
5713 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005714 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5715 ALOGV("%s: bus device set volume called", __func__);
5716 if (!out->standby)
5717 ret = out_set_pcm_volume(stream, left, right);
5718 out->volume_l = left;
5719 out->volume_r = right;
5720 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005721 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005723 return -ENOSYS;
5724}
5725
Zhou Songc9672822017-08-16 16:01:39 +08005726static void update_frames_written(struct stream_out *out, size_t bytes)
5727{
5728 size_t bpf = 0;
5729
5730 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5731 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5732 bpf = 1;
5733 else if (!is_offload_usecase(out->usecase))
5734 bpf = audio_bytes_per_sample(out->format) *
5735 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005736
5737 pthread_mutex_lock(&out->position_query_lock);
5738 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005739 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005740 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5741 }
5742 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005743}
5744
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005745int split_and_write_audio_haptic_data(struct stream_out *out,
5746 const void *buffer, size_t bytes_to_write)
5747{
5748 struct audio_device *adev = out->dev;
5749
5750 int ret = 0;
5751 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5752 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5753 size_t frame_size = channel_count * bytes_per_sample;
5754 size_t frame_count = bytes_to_write / frame_size;
5755
5756 bool force_haptic_path =
5757 property_get_bool("vendor.audio.test_haptic", false);
5758
5759 // extract Haptics data from Audio buffer
5760 bool alloc_haptic_buffer = false;
5761 int haptic_channel_count = adev->haptics_config.channels;
5762 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5763 size_t audio_frame_size = frame_size - haptic_frame_size;
5764 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5765
5766 if (adev->haptic_buffer == NULL) {
5767 alloc_haptic_buffer = true;
5768 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5769 free(adev->haptic_buffer);
5770 adev->haptic_buffer_size = 0;
5771 alloc_haptic_buffer = true;
5772 }
5773
5774 if (alloc_haptic_buffer) {
5775 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005776 if(adev->haptic_buffer == NULL) {
5777 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5778 return -ENOMEM;
5779 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005780 adev->haptic_buffer_size = total_haptic_buffer_size;
5781 }
5782
5783 size_t src_index = 0, aud_index = 0, hap_index = 0;
5784 uint8_t *audio_buffer = (uint8_t *)buffer;
5785 uint8_t *haptic_buffer = adev->haptic_buffer;
5786
5787 // This is required for testing only. This works for stereo data only.
5788 // One channel is fed to audio stream and other to haptic stream for testing.
5789 if (force_haptic_path)
5790 audio_frame_size = haptic_frame_size = bytes_per_sample;
5791
5792 for (size_t i = 0; i < frame_count; i++) {
5793 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5794 audio_frame_size);
5795 aud_index += audio_frame_size;
5796 src_index += audio_frame_size;
5797
5798 if (adev->haptic_pcm)
5799 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5800 haptic_frame_size);
5801 hap_index += haptic_frame_size;
5802 src_index += haptic_frame_size;
5803
5804 // This is required for testing only.
5805 // Discard haptic channel data.
5806 if (force_haptic_path)
5807 src_index += haptic_frame_size;
5808 }
5809
5810 // write to audio pipeline
5811 ret = pcm_write(out->pcm, (void *)audio_buffer,
5812 frame_count * audio_frame_size);
5813
5814 // write to haptics pipeline
5815 if (adev->haptic_pcm)
5816 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5817 frame_count * haptic_frame_size);
5818
5819 return ret;
5820}
5821
Aalique Grahame22e49102018-12-18 14:23:57 -08005822#ifdef NO_AUDIO_OUT
5823static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5824 const void *buffer __unused, size_t bytes)
5825{
5826 struct stream_out *out = (struct stream_out *)stream;
5827
5828 /* No Output device supported other than BT for playback.
5829 * Sleep for the amount of buffer duration
5830 */
5831 lock_output_stream(out);
5832 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5833 (const struct audio_stream_out *)&out->stream) /
5834 out_get_sample_rate(&out->stream.common));
5835 pthread_mutex_unlock(&out->lock);
5836 return bytes;
5837}
5838#endif
5839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005840static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5841 size_t bytes)
5842{
5843 struct stream_out *out = (struct stream_out *)stream;
5844 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005845 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305846 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005847 const size_t frame_size = audio_stream_out_frame_size(stream);
5848 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305849 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005850 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005851
Haynes Mathew George380745d2017-10-04 15:27:45 -07005852 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005853 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305854
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305855 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005856
Dhananjay Kumarac341582017-02-23 23:42:25 +05305857 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305858 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305859 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5860 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005861 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305862 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305863 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305864 ALOGD(" %s: sound card is not active/SSR state", __func__);
5865 ret= -EIO;
5866 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305867 }
5868 }
5869
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305870 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305871 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305872 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305873 goto exit;
5874 }
5875
Haynes Mathew George16081042017-05-31 17:16:49 -07005876 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5877 ret = -EINVAL;
5878 goto exit;
5879 }
5880
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005881 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305882 !out->is_iec61937_info_available) {
5883
5884 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5885 out->is_iec61937_info_available = true;
5886 } else if (audio_extn_passthru_is_enabled()) {
5887 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305888 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305889
5890 if((out->format == AUDIO_FORMAT_DTS) ||
5891 (out->format == AUDIO_FORMAT_DTS_HD)) {
5892 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5893 buffer, bytes);
5894 if (ret) {
5895 if (ret != -ENOSYS) {
5896 out->is_iec61937_info_available = false;
5897 ALOGD("iec61937 transmission info not yet updated retry");
5898 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305899 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305900 /* if stream has started and after that there is
5901 * stream config change (iec transmission config)
5902 * then trigger select_device to update backend configuration.
5903 */
5904 out->stream_config_changed = true;
5905 pthread_mutex_lock(&adev->lock);
5906 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305907 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005908 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305909 ret = -EINVAL;
5910 goto exit;
5911 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305912 pthread_mutex_unlock(&adev->lock);
5913 out->stream_config_changed = false;
5914 out->is_iec61937_info_available = true;
5915 }
5916 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305917
Meng Wang4c32fb42020-01-16 17:57:11 +08005918#ifdef AUDIO_GKI_ENABLED
5919 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5920 compr_passthr = out->compr_config.codec->reserved[0];
5921#else
5922 compr_passthr = out->compr_config.codec->compr_passthr;
5923#endif
5924
Garmond Leung317cbf12017-09-13 16:20:50 -07005925 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005926 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305927 (out->is_iec61937_info_available == true)) {
5928 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5929 ret = -EINVAL;
5930 goto exit;
5931 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305932 }
5933 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305934
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005935 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005936 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005937 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5938 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005939 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305940 ret = -EIO;
5941 goto exit;
5942 }
5943 }
5944 }
5945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005946 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005947 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005948 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5949
Eric Laurent150dbfe2013-02-27 14:31:02 -08005950 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005951 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5952 ret = voice_extn_compress_voip_start_output_stream(out);
5953 else
5954 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005955 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005956 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005957 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005958 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005959 goto exit;
5960 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305961 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005962 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005963
5964 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005965 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005966 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305967 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005968 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005969 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305970
5971 if ((out->is_iec61937_info_available == true) &&
5972 (audio_extn_passthru_is_passthrough_stream(out))&&
5973 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5974 ret = -EINVAL;
5975 goto exit;
5976 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305977 if (out->set_dual_mono)
5978 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005979
5980 // log startup time in ms.
5981 simple_stats_log(
5982 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005983 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005984
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005985 if (adev->is_channel_status_set == false &&
5986 compare_device_type(&out->device_list,
5987 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005988 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305989 adev->is_channel_status_set = true;
5990 }
5991
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305992 if ((adev->use_old_pspd_mix_ctrl == true) &&
5993 (out->pspd_coeff_sent == false)) {
5994 /*
5995 * Need to resend pspd coefficients after stream started for
5996 * older kernel version as it does not save the coefficients
5997 * and also stream has to be started for coeff to apply.
5998 */
5999 usecase = get_usecase_from_list(adev, out->usecase);
6000 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306001 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306002 out->pspd_coeff_sent = true;
6003 }
6004 }
6005
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006006 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006007 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006008 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006009 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006010 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6011 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306012 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6013 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006014 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306015 out->send_next_track_params = false;
6016 out->is_compr_metadata_avail = false;
6017 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006018 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306019 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306020 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006021
Ashish Jain83a6cc22016-06-28 14:34:17 +05306022 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306023 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306024 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306025 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006026 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306027 return -EINVAL;
6028 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306029 audio_format_t dst_format = out->hal_op_format;
6030 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306031
Dieter Luecking5d57def2018-09-07 14:23:37 +02006032 /* prevent division-by-zero */
6033 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6034 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6035 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6036 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306037 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006038 ATRACE_END();
6039 return -EINVAL;
6040 }
6041
Ashish Jainf1eaa582016-05-23 20:54:24 +05306042 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6043 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6044
Ashish Jain83a6cc22016-06-28 14:34:17 +05306045 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306046 dst_format,
6047 buffer,
6048 src_format,
6049 frames);
6050
Ashish Jain83a6cc22016-06-28 14:34:17 +05306051 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306052 bytes_to_write);
6053
6054 /*Convert written bytes in audio flinger format*/
6055 if (ret > 0)
6056 ret = ((ret * format_to_bitwidth_table[out->format]) /
6057 format_to_bitwidth_table[dst_format]);
6058 }
6059 } else
6060 ret = compress_write(out->compr, buffer, bytes);
6061
Zhou Songc9672822017-08-16 16:01:39 +08006062 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6063 update_frames_written(out, bytes);
6064
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306065 if (ret < 0)
6066 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006067 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306068 /*msg to cb thread only if non blocking write is enabled*/
6069 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306070 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006071 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306072 } else if (-ENETRESET == ret) {
6073 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306074 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306075 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306076 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006077 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306078 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006079 }
Ashish Jain5106d362016-05-11 19:23:33 +05306080
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306081 /* Call compr start only when non-zero bytes of data is there to be rendered */
6082 if (!out->playback_started && ret > 0) {
6083 int status = compress_start(out->compr);
6084 if (status < 0) {
6085 ret = status;
6086 ALOGE("%s: compr start failed with err %d", __func__, errno);
6087 goto exit;
6088 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006089 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006090 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006091 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006092 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006093 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006094
6095 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6096 popcount(out->channel_mask),
6097 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006098 }
6099 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006100 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006101 return ret;
6102 } else {
6103 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006104 size_t bytes_to_write = bytes;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006105 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006106 if (out->muted)
6107 memset((void *)buffer, 0, bytes);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006108 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006109 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6110 __func__, frames, frame_size, bytes_to_write);
6111
Aalique Grahame22e49102018-12-18 14:23:57 -08006112 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006113 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6114 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6115 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006116 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6117 int16_t *src = (int16_t *)buffer;
6118 int16_t *dst = (int16_t *)buffer;
6119
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006120 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006121 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006122 "out_write called for %s use case with wrong properties",
6123 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006124
6125 /*
6126 * FIXME: this can be removed once audio flinger mixer supports
6127 * mono output
6128 */
6129
6130 /*
6131 * Code below goes over each frame in the buffer and adds both
6132 * L and R samples and then divides by 2 to convert to mono
6133 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006134 if (channel_count == 2) {
6135 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6136 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6137 }
6138 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006139 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006140 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006141
6142 // Note: since out_get_presentation_position() is called alternating with out_write()
6143 // by AudioFlinger, we can check underruns using the prior timestamp read.
6144 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6145 if (out->last_fifo_valid) {
6146 // compute drain to see if there is an underrun.
6147 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306148 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6149 int64_t frames_by_time =
6150 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6151 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006152 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6153
6154 if (underrun > 0) {
6155 simple_stats_log(&out->fifo_underruns, underrun);
6156
6157 ALOGW("%s: underrun(%lld) "
6158 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6159 __func__,
6160 (long long)out->fifo_underruns.n,
6161 (long long)frames_by_time,
6162 (long long)out->last_fifo_frames_remaining);
6163 }
6164 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6165 }
6166
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306167 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006168
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006169 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006170
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006171 if (out->config.rate)
6172 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6173 out->config.rate;
6174
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006175 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006176 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6177
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006178 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006179 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006180 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306181 out->convert_buffer != NULL) {
6182
6183 memcpy_by_audio_format(out->convert_buffer,
6184 out->hal_op_format,
6185 buffer,
6186 out->hal_ip_format,
6187 out->config.period_size * out->config.channels);
6188
6189 ret = pcm_write(out->pcm, out->convert_buffer,
6190 (out->config.period_size *
6191 out->config.channels *
6192 format_to_bitwidth_table[out->hal_op_format]));
6193 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306194 /*
6195 * To avoid underrun in DSP when the application is not pumping
6196 * data at required rate, check for the no. of bytes and ignore
6197 * pcm_write if it is less than actual buffer size.
6198 * It is a work around to a change in compress VOIP driver.
6199 */
6200 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6201 bytes < (out->config.period_size * out->config.channels *
6202 audio_bytes_per_sample(out->format))) {
6203 size_t voip_buf_size =
6204 out->config.period_size * out->config.channels *
6205 audio_bytes_per_sample(out->format);
6206 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6207 __func__, bytes, voip_buf_size);
6208 usleep(((uint64_t)voip_buf_size - bytes) *
6209 1000000 / audio_stream_out_frame_size(stream) /
6210 out_get_sample_rate(&out->stream.common));
6211 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006212 } else {
6213 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6214 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6215 else
6216 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6217 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306218 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006219
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006220 release_out_focus(out);
6221
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306222 if (ret < 0)
6223 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006224 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306225 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227 }
6228
6229exit:
Zhou Songc9672822017-08-16 16:01:39 +08006230 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306231 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306232 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006234 pthread_mutex_unlock(&out->lock);
6235
6236 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006237 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006238 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306239 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306240 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306241 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306242 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306243 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306244 out->standby = true;
6245 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306246 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006247 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6248 /* prevent division-by-zero */
6249 uint32_t stream_size = audio_stream_out_frame_size(stream);
6250 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006251
Dieter Luecking5d57def2018-09-07 14:23:37 +02006252 if ((stream_size == 0) || (srate == 0)) {
6253 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6254 ATRACE_END();
6255 return -EINVAL;
6256 }
6257 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6258 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006259 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306260 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006261 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006262 return ret;
6263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006264 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006265 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 return bytes;
6267}
6268
6269static int out_get_render_position(const struct audio_stream_out *stream,
6270 uint32_t *dsp_frames)
6271{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006272 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006273
6274 if (dsp_frames == NULL)
6275 return -EINVAL;
6276
6277 *dsp_frames = 0;
6278 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006279 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306280
6281 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6282 * this operation and adev_close_output_stream(where out gets reset).
6283 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306284 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006285 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306286 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006287 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306288 return 0;
6289 }
6290
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006291 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306292 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306293 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006294 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306295 if (ret < 0)
6296 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006297 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306298 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006299 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306300 if (-ENETRESET == ret) {
6301 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306302 out->card_status = CARD_STATUS_OFFLINE;
6303 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306304 } else if(ret < 0) {
6305 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306306 ret = -EINVAL;
6307 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306308 /*
6309 * Handle corner case where compress session is closed during SSR
6310 * and timestamp is queried
6311 */
6312 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306313 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306314 } else if (out->prev_card_status_offline) {
6315 ALOGE("ERROR: previously sound card was offline,return error");
6316 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306317 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306318 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006319 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306320 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306321 pthread_mutex_unlock(&out->lock);
6322 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006323 } else if (audio_is_linear_pcm(out->format)) {
6324 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006325 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006326 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006327 } else
6328 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006329}
6330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006331static int out_add_audio_effect(const struct audio_stream *stream __unused,
6332 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006333{
6334 return 0;
6335}
6336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006337static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6338 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006339{
6340 return 0;
6341}
6342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006343static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6344 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006345{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306346 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006347}
6348
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006349static int out_get_presentation_position(const struct audio_stream_out *stream,
6350 uint64_t *frames, struct timespec *timestamp)
6351{
6352 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306353 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006354 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006355
Ashish Jain5106d362016-05-11 19:23:33 +05306356 /* below piece of code is not guarded against any lock because audioFliner serializes
6357 * this operation and adev_close_output_stream( where out gets reset).
6358 */
6359 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306360 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006361 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306362 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6363 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6364 return 0;
6365 }
6366
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006367 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006368
Ashish Jain5106d362016-05-11 19:23:33 +05306369 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6370 ret = compress_get_tstamp(out->compr, &dsp_frames,
6371 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006372 // Adjustment accounts for A2dp encoder latency with offload usecases
6373 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006374 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006375 unsigned long offset =
6376 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6377 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6378 }
Ashish Jain5106d362016-05-11 19:23:33 +05306379 ALOGVV("%s rendered frames %ld sample_rate %d",
6380 __func__, dsp_frames, out->sample_rate);
6381 *frames = dsp_frames;
6382 if (ret < 0)
6383 ret = -errno;
6384 if (-ENETRESET == ret) {
6385 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306386 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306387 ret = -EINVAL;
6388 } else
6389 ret = 0;
6390 /* this is the best we can do */
6391 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006392 } else {
6393 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006394 unsigned int avail;
6395 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006396 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006397 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006398
Andy Hunga1f48fa2019-07-01 18:14:53 -07006399 if (out->kernel_buffer_size > avail) {
6400 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6401 } else {
6402 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6403 __func__, avail, out->kernel_buffer_size);
6404 avail = out->kernel_buffer_size;
6405 frames_temp = out->last_fifo_frames_remaining = 0;
6406 }
6407 out->last_fifo_valid = true;
6408 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6409
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006410 if (out->written >= frames_temp)
6411 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006412
Andy Hunga1f48fa2019-07-01 18:14:53 -07006413 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6414 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6415
Weiyin Jiangd4633762018-03-16 12:05:03 +08006416 // This adjustment accounts for buffering after app processor.
6417 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006418 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006419 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006420 if (signed_frames >= frames_temp)
6421 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006422
Weiyin Jiangd4633762018-03-16 12:05:03 +08006423 // Adjustment accounts for A2dp encoder latency with non offload usecases
6424 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006425 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006426 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6427 if (signed_frames >= frames_temp)
6428 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006429 }
6430
6431 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006432 *frames = signed_frames;
6433 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006434 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006435 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6436 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006437 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306438 *frames = out->written;
6439 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306440 if (is_offload_usecase(out->usecase))
6441 ret = -EINVAL;
6442 else
6443 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006444 }
6445 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006446 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006447 return ret;
6448}
6449
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006450static int out_set_callback(struct audio_stream_out *stream,
6451 stream_callback_t callback, void *cookie)
6452{
6453 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006454 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455
6456 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006457 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006458 out->client_callback = callback;
6459 out->client_cookie = cookie;
6460 if (out->adsp_hdlr_stream_handle) {
6461 ret = audio_extn_adsp_hdlr_stream_set_callback(
6462 out->adsp_hdlr_stream_handle,
6463 callback,
6464 cookie);
6465 if (ret)
6466 ALOGW("%s:adsp hdlr callback registration failed %d",
6467 __func__, ret);
6468 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006469 pthread_mutex_unlock(&out->lock);
6470 return 0;
6471}
6472
6473static int out_pause(struct audio_stream_out* stream)
6474{
6475 struct stream_out *out = (struct stream_out *)stream;
6476 int status = -ENOSYS;
6477 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006478 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006479 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306480 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006481 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006482 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006483 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306484 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306485 status = compress_pause(out->compr);
6486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006487 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006488
Mingming Yin21854652016-04-13 11:54:02 -07006489 if (audio_extn_passthru_is_active()) {
6490 ALOGV("offload use case, pause passthru");
6491 audio_extn_passthru_on_pause(out);
6492 }
6493
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306494 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006495 audio_extn_dts_notify_playback_state(out->usecase, 0,
6496 out->sample_rate, popcount(out->channel_mask),
6497 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006498 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006499 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006500 pthread_mutex_unlock(&out->lock);
6501 }
6502 return status;
6503}
6504
6505static int out_resume(struct audio_stream_out* stream)
6506{
6507 struct stream_out *out = (struct stream_out *)stream;
6508 int status = -ENOSYS;
6509 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006510 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006511 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306512 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006513 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006514 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006515 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306516 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306517 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006518 }
6519 if (!status) {
6520 out->offload_state = OFFLOAD_STATE_PLAYING;
6521 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306522 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006523 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6524 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006525 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006526 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006527 pthread_mutex_unlock(&out->lock);
6528 }
6529 return status;
6530}
6531
6532static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6533{
6534 struct stream_out *out = (struct stream_out *)stream;
6535 int status = -ENOSYS;
6536 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006537 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006538 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006539 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6540 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6541 else
6542 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6543 pthread_mutex_unlock(&out->lock);
6544 }
6545 return status;
6546}
6547
6548static int out_flush(struct audio_stream_out* stream)
6549{
6550 struct stream_out *out = (struct stream_out *)stream;
6551 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006552 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006553 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006554 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006555 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006556 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6557 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006558 } else {
6559 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6560 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006561 out->written = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006562 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006563 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006564 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006565 return 0;
6566 }
6567 return -ENOSYS;
6568}
6569
Haynes Mathew George16081042017-05-31 17:16:49 -07006570static int out_stop(const struct audio_stream_out* stream)
6571{
6572 struct stream_out *out = (struct stream_out *)stream;
6573 struct audio_device *adev = out->dev;
6574 int ret = -ENOSYS;
6575
6576 ALOGV("%s", __func__);
6577 pthread_mutex_lock(&adev->lock);
6578 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6579 out->playback_started && out->pcm != NULL) {
6580 pcm_stop(out->pcm);
6581 ret = stop_output_stream(out);
6582 out->playback_started = false;
6583 }
6584 pthread_mutex_unlock(&adev->lock);
6585 return ret;
6586}
6587
6588static int out_start(const struct audio_stream_out* stream)
6589{
6590 struct stream_out *out = (struct stream_out *)stream;
6591 struct audio_device *adev = out->dev;
6592 int ret = -ENOSYS;
6593
6594 ALOGV("%s", __func__);
6595 pthread_mutex_lock(&adev->lock);
6596 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6597 !out->playback_started && out->pcm != NULL) {
6598 ret = start_output_stream(out);
6599 if (ret == 0) {
6600 out->playback_started = true;
6601 }
6602 }
6603 pthread_mutex_unlock(&adev->lock);
6604 return ret;
6605}
6606
6607/*
6608 * Modify config->period_count based on min_size_frames
6609 */
6610static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6611{
6612 int periodCountRequested = (min_size_frames + config->period_size - 1)
6613 / config->period_size;
6614 int periodCount = MMAP_PERIOD_COUNT_MIN;
6615
6616 ALOGV("%s original config.period_size = %d config.period_count = %d",
6617 __func__, config->period_size, config->period_count);
6618
6619 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6620 periodCount *= 2;
6621 }
6622 config->period_count = periodCount;
6623
6624 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6625}
6626
Phil Burkfe17efd2019-03-25 10:23:35 -07006627// Read offset for the positional timestamp from a persistent vendor property.
6628// This is to workaround apparent inaccuracies in the timing information that
6629// is used by the AAudio timing model. The inaccuracies can cause glitches.
6630static int64_t get_mmap_out_time_offset() {
6631 const int32_t kDefaultOffsetMicros = 0;
6632 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006633 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006634 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6635 return mmap_time_offset_micros * (int64_t)1000;
6636}
6637
Haynes Mathew George16081042017-05-31 17:16:49 -07006638static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6639 int32_t min_size_frames,
6640 struct audio_mmap_buffer_info *info)
6641{
6642 struct stream_out *out = (struct stream_out *)stream;
6643 struct audio_device *adev = out->dev;
6644 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006645 unsigned int offset1 = 0;
6646 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006647 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006648 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006649 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006650
Arun Mirpuri5d170872019-03-26 13:21:31 -07006651 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306652 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006653 pthread_mutex_lock(&adev->lock);
6654
Sharad Sanglec6f32552018-05-04 16:15:38 +05306655 if (CARD_STATUS_OFFLINE == out->card_status ||
6656 CARD_STATUS_OFFLINE == adev->card_status) {
6657 ALOGW("out->card_status or adev->card_status offline, try again");
6658 ret = -EIO;
6659 goto exit;
6660 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306661 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006662 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6663 ret = -EINVAL;
6664 goto exit;
6665 }
6666 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6667 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6668 ret = -ENOSYS;
6669 goto exit;
6670 }
6671 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6672 if (out->pcm_device_id < 0) {
6673 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6674 __func__, out->pcm_device_id, out->usecase);
6675 ret = -EINVAL;
6676 goto exit;
6677 }
6678
6679 adjust_mmap_period_count(&out->config, min_size_frames);
6680
Arun Mirpuri5d170872019-03-26 13:21:31 -07006681 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006682 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6683 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6684 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306685 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306686 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6687 out->card_status = CARD_STATUS_OFFLINE;
6688 adev->card_status = CARD_STATUS_OFFLINE;
6689 ret = -EIO;
6690 goto exit;
6691 }
6692
Haynes Mathew George16081042017-05-31 17:16:49 -07006693 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6694 step = "open";
6695 ret = -ENODEV;
6696 goto exit;
6697 }
6698 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6699 if (ret < 0) {
6700 step = "begin";
6701 goto exit;
6702 }
juyuchen626833d2019-06-04 16:48:02 +08006703
6704 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006705 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006706 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006707 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006708 ret = platform_get_mmap_data_fd(adev->platform,
6709 out->pcm_device_id, 0 /*playback*/,
6710 &info->shared_memory_fd,
6711 &mmap_size);
6712 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006713 // Fall back to non exclusive mode
6714 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6715 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006716 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6717 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6718
Arun Mirpuri5d170872019-03-26 13:21:31 -07006719 if (mmap_size < buffer_size) {
6720 step = "mmap";
6721 goto exit;
6722 }
juyuchen626833d2019-06-04 16:48:02 +08006723 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006724 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006725 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006726 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006727
6728 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6729 if (ret < 0) {
6730 step = "commit";
6731 goto exit;
6732 }
6733
Phil Burkfe17efd2019-03-25 10:23:35 -07006734 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6735
Haynes Mathew George16081042017-05-31 17:16:49 -07006736 out->standby = false;
6737 ret = 0;
6738
Arun Mirpuri5d170872019-03-26 13:21:31 -07006739 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006740 __func__, info->shared_memory_address, info->buffer_size_frames);
6741
6742exit:
6743 if (ret != 0) {
6744 if (out->pcm == NULL) {
6745 ALOGE("%s: %s - %d", __func__, step, ret);
6746 } else {
6747 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6748 pcm_close(out->pcm);
6749 out->pcm = NULL;
6750 }
6751 }
6752 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306753 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006754 return ret;
6755}
6756
6757static int out_get_mmap_position(const struct audio_stream_out *stream,
6758 struct audio_mmap_position *position)
6759{
6760 struct stream_out *out = (struct stream_out *)stream;
6761 ALOGVV("%s", __func__);
6762 if (position == NULL) {
6763 return -EINVAL;
6764 }
6765 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006766 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006767 return -ENOSYS;
6768 }
6769 if (out->pcm == NULL) {
6770 return -ENOSYS;
6771 }
6772
6773 struct timespec ts = { 0, 0 };
6774 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6775 if (ret < 0) {
6776 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6777 return ret;
6778 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006779 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6780 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006781 return 0;
6782}
6783
6784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785/** audio_stream_in implementation **/
6786static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6787{
6788 struct stream_in *in = (struct stream_in *)stream;
6789
6790 return in->config.rate;
6791}
6792
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006793static int in_set_sample_rate(struct audio_stream *stream __unused,
6794 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006795{
6796 return -ENOSYS;
6797}
6798
6799static size_t in_get_buffer_size(const struct audio_stream *stream)
6800{
6801 struct stream_in *in = (struct stream_in *)stream;
6802
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006803 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6804 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006805 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6806 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306807 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306808 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006809
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006810 return in->config.period_size * in->af_period_multiplier *
6811 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006812}
6813
6814static uint32_t in_get_channels(const struct audio_stream *stream)
6815{
6816 struct stream_in *in = (struct stream_in *)stream;
6817
6818 return in->channel_mask;
6819}
6820
6821static audio_format_t in_get_format(const struct audio_stream *stream)
6822{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006823 struct stream_in *in = (struct stream_in *)stream;
6824
6825 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006826}
6827
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006828static int in_set_format(struct audio_stream *stream __unused,
6829 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006830{
6831 return -ENOSYS;
6832}
6833
6834static int in_standby(struct audio_stream *stream)
6835{
6836 struct stream_in *in = (struct stream_in *)stream;
6837 struct audio_device *adev = in->dev;
6838 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306839 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6840 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006841 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306842
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006843 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006844 if (!in->standby && in->is_st_session) {
6845 ALOGD("%s: sound trigger pcm stop lab", __func__);
6846 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006847 if (adev->num_va_sessions > 0)
6848 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006849 in->standby = 1;
6850 }
6851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006853 if (adev->adm_deregister_stream)
6854 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6855
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006856 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006857 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006858 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006859 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006860 voice_extn_compress_voip_close_input_stream(stream);
6861 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006862 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6863 do_stop = in->capture_started;
6864 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006865 if (in->mmap_shared_memory_fd >= 0) {
6866 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6867 __func__, in->mmap_shared_memory_fd);
6868 close(in->mmap_shared_memory_fd);
6869 in->mmap_shared_memory_fd = -1;
6870 }
Zhou Songa8895042016-07-05 17:54:22 +08006871 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306872 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306873 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006874 }
6875
Arun Mirpuri5d170872019-03-26 13:21:31 -07006876 if (in->pcm) {
6877 ATRACE_BEGIN("pcm_in_close");
6878 pcm_close(in->pcm);
6879 ATRACE_END();
6880 in->pcm = NULL;
6881 }
6882
Carter Hsu2e429db2019-05-14 18:50:52 +08006883 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006884 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006885
George Gao3018ede2019-10-23 13:23:00 -07006886 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6887 if (adev->num_va_sessions > 0)
6888 adev->num_va_sessions--;
6889 }
Quinn Malef6050362019-01-30 15:55:40 -08006890
Eric Laurent150dbfe2013-02-27 14:31:02 -08006891 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006892 }
6893 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006894 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006895 return status;
6896}
6897
Aalique Grahame22e49102018-12-18 14:23:57 -08006898static int in_dump(const struct audio_stream *stream,
6899 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006900{
Aalique Grahame22e49102018-12-18 14:23:57 -08006901 struct stream_in *in = (struct stream_in *)stream;
6902
6903 // We try to get the lock for consistency,
6904 // but it isn't necessary for these variables.
6905 // If we're not in standby, we may be blocked on a read.
6906 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6907 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6908 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6909 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6910
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006911 char buffer[256]; // for statistics formatting
6912 if (in->start_latency_ms.n > 0) {
6913 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6914 dprintf(fd, " Start latency ms: %s\n", buffer);
6915 }
6916
Aalique Grahame22e49102018-12-18 14:23:57 -08006917 if (locked) {
6918 pthread_mutex_unlock(&in->lock);
6919 }
6920
6921 // dump error info
6922 (void)error_log_dump(
6923 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006925 return 0;
6926}
6927
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306928static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6929{
6930 if (!stream || !parms)
6931 return;
6932
6933 struct stream_in *in = (struct stream_in *)stream;
6934 struct audio_device *adev = in->dev;
6935
6936 card_status_t status;
6937 int card;
6938 if (parse_snd_card_status(parms, &card, &status) < 0)
6939 return;
6940
6941 pthread_mutex_lock(&adev->lock);
6942 bool valid_cb = (card == adev->snd_card);
6943 pthread_mutex_unlock(&adev->lock);
6944
6945 if (!valid_cb)
6946 return;
6947
6948 lock_input_stream(in);
6949 if (in->card_status != status)
6950 in->card_status = status;
6951 pthread_mutex_unlock(&in->lock);
6952
6953 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6954 use_case_table[in->usecase],
6955 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6956
6957 // a better solution would be to report error back to AF and let
6958 // it put the stream to standby
6959 if (status == CARD_STATUS_OFFLINE)
6960 in_standby(&in->stream.common);
6961
6962 return;
6963}
6964
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006965int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006966 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006967 audio_source_t source)
6968{
6969 struct audio_device *adev = in->dev;
6970 int ret = 0;
6971
6972 lock_input_stream(in);
6973 pthread_mutex_lock(&adev->lock);
6974
6975 /* no audio source uses val == 0 */
6976 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6977 in->source = source;
6978 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6979 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6980 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6981 (in->config.rate == 8000 || in->config.rate == 16000 ||
6982 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6983 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6984 ret = voice_extn_compress_voip_open_input_stream(in);
6985 if (ret != 0) {
6986 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6987 __func__, ret);
6988 }
6989 }
6990 }
6991
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006992 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6993 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006994 // Workaround: If routing to an non existing usb device, fail gracefully
6995 // The routing request will otherwise block during 10 second
6996 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006997 struct str_parms *usb_addr =
6998 str_parms_create_str(get_usb_device_address(devices));
6999 if (is_usb_in_device_type(devices) && usb_addr &&
7000 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007001 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
7002 ret = -ENOSYS;
7003 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007004 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007005 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007006 if (!in->standby && !in->is_st_session) {
7007 ALOGV("update input routing change");
7008 // inform adm before actual routing to prevent glitches.
7009 if (adev->adm_on_routing_change) {
7010 adev->adm_on_routing_change(adev->adm_data,
7011 in->capture_handle);
7012 ret = select_devices(adev, in->usecase);
7013 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7014 adev->adm_routing_changed = true;
7015 }
7016 }
7017 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007018 if (usb_addr)
7019 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007020 }
7021 pthread_mutex_unlock(&adev->lock);
7022 pthread_mutex_unlock(&in->lock);
7023
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007024 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007025 return ret;
7026}
7027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007028static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7029{
7030 struct stream_in *in = (struct stream_in *)stream;
7031 struct audio_device *adev = in->dev;
7032 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007033 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307034 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007035
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307036 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007037 parms = str_parms_create_str(kvpairs);
7038
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307039 if (!parms)
7040 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007041 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007042 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007043
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307044 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7045 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307046 strlcpy(in->profile, value, sizeof(in->profile));
7047 ALOGV("updating stream profile with value '%s'", in->profile);
7048 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7049 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007050 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307051 in->sample_rate, in->bit_width,
7052 in->profile, &in->app_type_cfg);
7053 }
7054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007055 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007056 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007057
7058 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307059error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307060 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061}
7062
7063static char* in_get_parameters(const struct audio_stream *stream,
7064 const char *keys)
7065{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007066 struct stream_in *in = (struct stream_in *)stream;
7067 struct str_parms *query = str_parms_create_str(keys);
7068 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007069 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007070
7071 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007072 if (reply) {
7073 str_parms_destroy(reply);
7074 }
7075 if (query) {
7076 str_parms_destroy(query);
7077 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007078 ALOGE("in_get_parameters: failed to create query or reply");
7079 return NULL;
7080 }
7081
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007082 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007083
7084 voice_extn_in_get_parameters(in, query, reply);
7085
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007086 stream_get_parameter_channels(query, reply,
7087 &in->supported_channel_masks[0]);
7088 stream_get_parameter_formats(query, reply,
7089 &in->supported_formats[0]);
7090 stream_get_parameter_rates(query, reply,
7091 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007092 str = str_parms_to_str(reply);
7093 str_parms_destroy(query);
7094 str_parms_destroy(reply);
7095
7096 ALOGV("%s: exit: returns - %s", __func__, str);
7097 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007098}
7099
Aalique Grahame22e49102018-12-18 14:23:57 -08007100static int in_set_gain(struct audio_stream_in *stream,
7101 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007102{
Aalique Grahame22e49102018-12-18 14:23:57 -08007103 struct stream_in *in = (struct stream_in *)stream;
7104 char mixer_ctl_name[128];
7105 struct mixer_ctl *ctl;
7106 int ctl_value;
7107
7108 ALOGV("%s: gain %f", __func__, gain);
7109
7110 if (stream == NULL)
7111 return -EINVAL;
7112
7113 /* in_set_gain() only used to silence MMAP capture for now */
7114 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7115 return -ENOSYS;
7116
7117 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7118
7119 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7120 if (!ctl) {
7121 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7122 __func__, mixer_ctl_name);
7123 return -ENOSYS;
7124 }
7125
7126 if (gain < RECORD_GAIN_MIN)
7127 gain = RECORD_GAIN_MIN;
7128 else if (gain > RECORD_GAIN_MAX)
7129 gain = RECORD_GAIN_MAX;
7130 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7131
7132 mixer_ctl_set_value(ctl, 0, ctl_value);
7133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134 return 0;
7135}
7136
7137static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7138 size_t bytes)
7139{
7140 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307141
7142 if (in == NULL) {
7143 ALOGE("%s: stream_in ptr is NULL", __func__);
7144 return -EINVAL;
7145 }
7146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307148 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307149 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007150
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007151 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307152
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007153 if (in->is_st_session) {
7154 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7155 /* Read from sound trigger HAL */
7156 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007157 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007158 if (adev->num_va_sessions < UINT_MAX)
7159 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007160 in->standby = 0;
7161 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007162 pthread_mutex_unlock(&in->lock);
7163 return bytes;
7164 }
7165
Haynes Mathew George16081042017-05-31 17:16:49 -07007166 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7167 ret = -ENOSYS;
7168 goto exit;
7169 }
7170
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007171 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7172 !in->standby && adev->adm_routing_changed) {
7173 ret = -ENOSYS;
7174 goto exit;
7175 }
7176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007177 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007178 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7179
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007180 pthread_mutex_lock(&adev->lock);
7181 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7182 ret = voice_extn_compress_voip_start_input_stream(in);
7183 else
7184 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007185 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7186 if (adev->num_va_sessions < UINT_MAX)
7187 adev->num_va_sessions++;
7188 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007189 pthread_mutex_unlock(&adev->lock);
7190 if (ret != 0) {
7191 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007192 }
7193 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007194
7195 // log startup time in ms.
7196 simple_stats_log(
7197 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307200 /* Avoid read if capture_stopped is set */
7201 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7202 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7203 ret = -EINVAL;
7204 goto exit;
7205 }
7206
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007207 // what's the duration requested by the client?
7208 long ns = 0;
7209
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307210 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007211 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7212 in->config.rate;
7213
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007214 ret = request_in_focus(in, ns);
7215 if (ret != 0)
7216 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007217 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007218
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307219 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307220 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7221 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307222 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007223 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307224 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007225 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007226 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007227 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007228 } else if (audio_extn_ffv_get_stream() == in) {
7229 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307230 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007231 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307232 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7233 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7234 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7235 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307236 ret = -EINVAL;
7237 goto exit;
7238 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307239 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307240 ret = -errno;
7241 }
7242 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307243 /* bytes read is always set to bytes for non compress usecases */
7244 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245 }
7246
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007247 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249 /*
Quinn Malef6050362019-01-30 15:55:40 -08007250 * Instead of writing zeroes here, we could trust the hardware to always
7251 * provide zeroes when muted. This is also muted with voice recognition
7252 * usecases so that other clients do not have access to voice recognition
7253 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007254 */
Quinn Malef6050362019-01-30 15:55:40 -08007255 if ((ret == 0 && voice_get_mic_mute(adev) &&
7256 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007257 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7258 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007259 (adev->num_va_sessions &&
7260 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7261 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7262 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007263 memset(buffer, 0, bytes);
7264
7265exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307266 frame_size = audio_stream_in_frame_size(stream);
7267 if (frame_size > 0)
7268 in->frames_read += bytes_read/frame_size;
7269
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007270 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307271 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007272 pthread_mutex_unlock(&in->lock);
7273
7274 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307275 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307276 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307277 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307278 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307279 in->standby = true;
7280 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307281 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307282 bytes_read = bytes;
7283 memset(buffer, 0, bytes);
7284 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007286 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7287 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007288 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307289 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307290 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307292 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007293}
7294
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007295static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007296{
7297 return 0;
7298}
7299
Aalique Grahame22e49102018-12-18 14:23:57 -08007300static int in_get_capture_position(const struct audio_stream_in *stream,
7301 int64_t *frames, int64_t *time)
7302{
7303 if (stream == NULL || frames == NULL || time == NULL) {
7304 return -EINVAL;
7305 }
7306 struct stream_in *in = (struct stream_in *)stream;
7307 int ret = -ENOSYS;
7308
7309 lock_input_stream(in);
7310 // note: ST sessions do not close the alsa pcm driver synchronously
7311 // on standby. Therefore, we may return an error even though the
7312 // pcm stream is still opened.
7313 if (in->standby) {
7314 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7315 "%s stream in standby but pcm not NULL for non ST session", __func__);
7316 goto exit;
7317 }
7318 if (in->pcm) {
7319 struct timespec timestamp;
7320 unsigned int avail;
7321 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7322 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007323 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007324 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007325 ret = 0;
7326 }
7327 }
7328exit:
7329 pthread_mutex_unlock(&in->lock);
7330 return ret;
7331}
7332
Carter Hsu2e429db2019-05-14 18:50:52 +08007333static int in_update_effect_list(bool add, effect_handle_t effect,
7334 struct listnode *head)
7335{
7336 struct listnode *node;
7337 struct in_effect_list *elist = NULL;
7338 struct in_effect_list *target = NULL;
7339 int ret = 0;
7340
7341 if (!head)
7342 return ret;
7343
7344 list_for_each(node, head) {
7345 elist = node_to_item(node, struct in_effect_list, list);
7346 if (elist->handle == effect) {
7347 target = elist;
7348 break;
7349 }
7350 }
7351
7352 if (add) {
7353 if (target) {
7354 ALOGD("effect %p already exist", effect);
7355 return ret;
7356 }
7357
7358 target = (struct in_effect_list *)
7359 calloc(1, sizeof(struct in_effect_list));
7360
7361 if (!target) {
7362 ALOGE("%s:fail to allocate memory", __func__);
7363 return -ENOMEM;
7364 }
7365
7366 target->handle = effect;
7367 list_add_tail(head, &target->list);
7368 } else {
7369 if (target) {
7370 list_remove(&target->list);
7371 free(target);
7372 }
7373 }
7374
7375 return ret;
7376}
7377
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007378static int add_remove_audio_effect(const struct audio_stream *stream,
7379 effect_handle_t effect,
7380 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007381{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007382 struct stream_in *in = (struct stream_in *)stream;
7383 int status = 0;
7384 effect_descriptor_t desc;
7385
7386 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007387 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7388
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007389 if (status != 0)
7390 return status;
7391
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007392 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007393 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007394 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007395 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7396 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007397 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007398
7399 in_update_effect_list(enable, effect, &in->aec_list);
7400 enable = !list_empty(&in->aec_list);
7401 if (enable == in->enable_aec)
7402 goto exit;
7403
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007404 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007405 ALOGD("AEC enable %d", enable);
7406
Aalique Grahame22e49102018-12-18 14:23:57 -08007407 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7408 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7409 in->dev->enable_voicerx = enable;
7410 struct audio_usecase *usecase;
7411 struct listnode *node;
7412 list_for_each(node, &in->dev->usecase_list) {
7413 usecase = node_to_item(node, struct audio_usecase, list);
7414 if (usecase->type == PCM_PLAYBACK)
7415 select_devices(in->dev, usecase->id);
7416 }
7417 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007418 if (!in->standby) {
7419 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7420 select_devices(in->dev, in->usecase);
7421 }
7422
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007423 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007424 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7425
7426 in_update_effect_list(enable, effect, &in->ns_list);
7427 enable = !list_empty(&in->ns_list);
7428 if (enable == in->enable_ns)
7429 goto exit;
7430
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007431 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007432 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007433 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007434 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7435 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007436 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7437 select_devices(in->dev, in->usecase);
7438 } else
7439 select_devices(in->dev, in->usecase);
7440 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007441 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007442exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007443 pthread_mutex_unlock(&in->dev->lock);
7444 pthread_mutex_unlock(&in->lock);
7445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007446 return 0;
7447}
7448
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007449static int in_add_audio_effect(const struct audio_stream *stream,
7450 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007451{
Eric Laurent994a6932013-07-17 11:51:42 -07007452 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007453 return add_remove_audio_effect(stream, effect, true);
7454}
7455
7456static int in_remove_audio_effect(const struct audio_stream *stream,
7457 effect_handle_t effect)
7458{
Eric Laurent994a6932013-07-17 11:51:42 -07007459 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007460 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007461}
7462
Derek Chenf939fb72018-11-13 13:34:41 -08007463streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7464 audio_io_handle_t input)
7465{
7466 struct listnode *node;
7467
7468 list_for_each(node, &dev->active_inputs_list) {
7469 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7470 streams_input_ctxt_t,
7471 list);
7472 if (in_ctxt->input->capture_handle == input) {
7473 return in_ctxt;
7474 }
7475 }
7476 return NULL;
7477}
7478
7479streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7480 audio_io_handle_t output)
7481{
7482 struct listnode *node;
7483
7484 list_for_each(node, &dev->active_outputs_list) {
7485 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7486 streams_output_ctxt_t,
7487 list);
7488 if (out_ctxt->output->handle == output) {
7489 return out_ctxt;
7490 }
7491 }
7492 return NULL;
7493}
7494
Haynes Mathew George16081042017-05-31 17:16:49 -07007495static int in_stop(const struct audio_stream_in* stream)
7496{
7497 struct stream_in *in = (struct stream_in *)stream;
7498 struct audio_device *adev = in->dev;
7499
7500 int ret = -ENOSYS;
7501 ALOGV("%s", __func__);
7502 pthread_mutex_lock(&adev->lock);
7503 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7504 in->capture_started && in->pcm != NULL) {
7505 pcm_stop(in->pcm);
7506 ret = stop_input_stream(in);
7507 in->capture_started = false;
7508 }
7509 pthread_mutex_unlock(&adev->lock);
7510 return ret;
7511}
7512
7513static int in_start(const struct audio_stream_in* stream)
7514{
7515 struct stream_in *in = (struct stream_in *)stream;
7516 struct audio_device *adev = in->dev;
7517 int ret = -ENOSYS;
7518
7519 ALOGV("%s in %p", __func__, in);
7520 pthread_mutex_lock(&adev->lock);
7521 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7522 !in->capture_started && in->pcm != NULL) {
7523 if (!in->capture_started) {
7524 ret = start_input_stream(in);
7525 if (ret == 0) {
7526 in->capture_started = true;
7527 }
7528 }
7529 }
7530 pthread_mutex_unlock(&adev->lock);
7531 return ret;
7532}
7533
Phil Burke0a86d12019-02-16 22:28:11 -08007534// Read offset for the positional timestamp from a persistent vendor property.
7535// This is to workaround apparent inaccuracies in the timing information that
7536// is used by the AAudio timing model. The inaccuracies can cause glitches.
7537static int64_t in_get_mmap_time_offset() {
7538 const int32_t kDefaultOffsetMicros = 0;
7539 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007540 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007541 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7542 return mmap_time_offset_micros * (int64_t)1000;
7543}
7544
Haynes Mathew George16081042017-05-31 17:16:49 -07007545static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7546 int32_t min_size_frames,
7547 struct audio_mmap_buffer_info *info)
7548{
7549 struct stream_in *in = (struct stream_in *)stream;
7550 struct audio_device *adev = in->dev;
7551 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007552 unsigned int offset1 = 0;
7553 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007554 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007555 uint32_t mmap_size = 0;
7556 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007557
7558 pthread_mutex_lock(&adev->lock);
7559 ALOGV("%s in %p", __func__, in);
7560
Sharad Sanglec6f32552018-05-04 16:15:38 +05307561 if (CARD_STATUS_OFFLINE == in->card_status||
7562 CARD_STATUS_OFFLINE == adev->card_status) {
7563 ALOGW("in->card_status or adev->card_status offline, try again");
7564 ret = -EIO;
7565 goto exit;
7566 }
7567
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307568 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007569 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7570 ret = -EINVAL;
7571 goto exit;
7572 }
7573 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7574 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7575 ALOGV("%s in %p", __func__, in);
7576 ret = -ENOSYS;
7577 goto exit;
7578 }
7579 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7580 if (in->pcm_device_id < 0) {
7581 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7582 __func__, in->pcm_device_id, in->usecase);
7583 ret = -EINVAL;
7584 goto exit;
7585 }
7586
7587 adjust_mmap_period_count(&in->config, min_size_frames);
7588
7589 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7590 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7591 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7592 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307593 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307594 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7595 in->card_status = CARD_STATUS_OFFLINE;
7596 adev->card_status = CARD_STATUS_OFFLINE;
7597 ret = -EIO;
7598 goto exit;
7599 }
7600
Haynes Mathew George16081042017-05-31 17:16:49 -07007601 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7602 step = "open";
7603 ret = -ENODEV;
7604 goto exit;
7605 }
7606
7607 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7608 if (ret < 0) {
7609 step = "begin";
7610 goto exit;
7611 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007612
juyuchen626833d2019-06-04 16:48:02 +08007613 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007614 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7615 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7616 info->burst_size_frames = in->config.period_size;
7617 ret = platform_get_mmap_data_fd(adev->platform,
7618 in->pcm_device_id, 1 /*capture*/,
7619 &info->shared_memory_fd,
7620 &mmap_size);
7621 if (ret < 0) {
7622 // Fall back to non exclusive mode
7623 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7624 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007625 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7626 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7627
Arun Mirpuri5d170872019-03-26 13:21:31 -07007628 if (mmap_size < buffer_size) {
7629 step = "mmap";
7630 goto exit;
7631 }
juyuchen626833d2019-06-04 16:48:02 +08007632 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007633 }
7634
7635 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007636
7637 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7638 if (ret < 0) {
7639 step = "commit";
7640 goto exit;
7641 }
7642
Phil Burke0a86d12019-02-16 22:28:11 -08007643 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7644
Haynes Mathew George16081042017-05-31 17:16:49 -07007645 in->standby = false;
7646 ret = 0;
7647
7648 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7649 __func__, info->shared_memory_address, info->buffer_size_frames);
7650
7651exit:
7652 if (ret != 0) {
7653 if (in->pcm == NULL) {
7654 ALOGE("%s: %s - %d", __func__, step, ret);
7655 } else {
7656 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7657 pcm_close(in->pcm);
7658 in->pcm = NULL;
7659 }
7660 }
7661 pthread_mutex_unlock(&adev->lock);
7662 return ret;
7663}
7664
7665static int in_get_mmap_position(const struct audio_stream_in *stream,
7666 struct audio_mmap_position *position)
7667{
7668 struct stream_in *in = (struct stream_in *)stream;
7669 ALOGVV("%s", __func__);
7670 if (position == NULL) {
7671 return -EINVAL;
7672 }
7673 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7674 return -ENOSYS;
7675 }
7676 if (in->pcm == NULL) {
7677 return -ENOSYS;
7678 }
7679 struct timespec ts = { 0, 0 };
7680 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7681 if (ret < 0) {
7682 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7683 return ret;
7684 }
Phil Burke0a86d12019-02-16 22:28:11 -08007685 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7686 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007687 return 0;
7688}
7689
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307690static int in_get_active_microphones(const struct audio_stream_in *stream,
7691 struct audio_microphone_characteristic_t *mic_array,
7692 size_t *mic_count) {
7693 struct stream_in *in = (struct stream_in *)stream;
7694 struct audio_device *adev = in->dev;
7695 ALOGVV("%s", __func__);
7696
7697 lock_input_stream(in);
7698 pthread_mutex_lock(&adev->lock);
7699 int ret = platform_get_active_microphones(adev->platform,
7700 audio_channel_count_from_in_mask(in->channel_mask),
7701 in->usecase, mic_array, mic_count);
7702 pthread_mutex_unlock(&adev->lock);
7703 pthread_mutex_unlock(&in->lock);
7704
7705 return ret;
7706}
7707
7708static int adev_get_microphones(const struct audio_hw_device *dev,
7709 struct audio_microphone_characteristic_t *mic_array,
7710 size_t *mic_count) {
7711 struct audio_device *adev = (struct audio_device *)dev;
7712 ALOGVV("%s", __func__);
7713
7714 pthread_mutex_lock(&adev->lock);
7715 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7716 pthread_mutex_unlock(&adev->lock);
7717
7718 return ret;
7719}
juyuchendb308c22019-01-21 11:57:17 -07007720
7721static void in_update_sink_metadata(struct audio_stream_in *stream,
7722 const struct sink_metadata *sink_metadata) {
7723
7724 if (stream == NULL
7725 || sink_metadata == NULL
7726 || sink_metadata->tracks == NULL) {
7727 return;
7728 }
7729
7730 int error = 0;
7731 struct stream_in *in = (struct stream_in *)stream;
7732 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007733 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007734 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007735
7736 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007737
7738 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007739 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007740
7741 lock_input_stream(in);
7742 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007743 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007744
Zhou Song62ea0282020-03-22 19:53:01 +08007745 is_ha_usecase = adev->ha_proxy_enable ?
7746 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7747 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7748 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007749 && adev->voice_tx_output != NULL) {
7750 /* Use the rx device from afe-proxy record to route voice call because
7751 there is no routing if tx device is on primary hal and rx device
7752 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007753 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007754
7755 if (!voice_is_call_state_active(adev)) {
7756 if (adev->mode == AUDIO_MODE_IN_CALL) {
7757 adev->current_call_output = adev->voice_tx_output;
7758 error = voice_start_call(adev);
7759 if (error != 0)
7760 ALOGE("%s: start voice call failed %d", __func__, error);
7761 }
7762 } else {
7763 adev->current_call_output = adev->voice_tx_output;
7764 voice_update_devices_for_all_voice_usecases(adev);
7765 }
7766 }
7767
7768 pthread_mutex_unlock(&adev->lock);
7769 pthread_mutex_unlock(&in->lock);
7770}
7771
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307772int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007773 audio_io_handle_t handle,
7774 audio_devices_t devices,
7775 audio_output_flags_t flags,
7776 struct audio_config *config,
7777 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007778 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007779{
7780 struct audio_device *adev = (struct audio_device *)dev;
7781 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307782 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007783 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007784 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307785 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007786 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7787 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7788 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7789 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007790 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007791 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7792 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007793 bool force_haptic_path =
7794 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007795 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007796#ifdef AUDIO_GKI_ENABLED
7797 __s32 *generic_dec;
7798#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007799
kunleizdff872d2018-08-20 14:40:33 +08007800 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007801 is_usb_dev = false;
7802 devices = AUDIO_DEVICE_OUT_SPEAKER;
7803 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7804 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007805 if (config->format == AUDIO_FORMAT_DEFAULT)
7806 config->format = AUDIO_FORMAT_PCM_16_BIT;
7807 if (config->sample_rate == 0)
7808 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7809 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7810 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007811 }
7812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007813 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307814
Rahul Sharma99770982019-03-06 17:05:26 +05307815 pthread_mutex_lock(&adev->lock);
7816 if (out_get_stream(adev, handle) != NULL) {
7817 ALOGW("%s, output stream already opened", __func__);
7818 ret = -EEXIST;
7819 }
7820 pthread_mutex_unlock(&adev->lock);
7821 if (ret)
7822 return ret;
7823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007824 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7825
Mingming Yin3a941d42016-02-17 18:08:05 -08007826 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007827 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7828 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307829
7830
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007831 if (!out) {
7832 return -ENOMEM;
7833 }
7834
Haynes Mathew George204045b2015-02-25 20:32:03 -08007835 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007836 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007837 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007838 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007839 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007841 if (devices == AUDIO_DEVICE_NONE)
7842 devices = AUDIO_DEVICE_OUT_SPEAKER;
7843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007844 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007845 list_init(&out->device_list);
7846 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007847 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007848 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007849 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307850 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307851 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7852 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7853 else
7854 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007855 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007856 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007857 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307858 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307859 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307860 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007861 out->hal_output_suspend_supported = 0;
7862 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307863 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307864 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307865 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007866 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007867
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307868 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307869 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007870 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7871
Aalique Grahame22e49102018-12-18 14:23:57 -08007872 if (direct_dev &&
7873 (audio_is_linear_pcm(out->format) ||
7874 config->format == AUDIO_FORMAT_DEFAULT) &&
7875 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7876 audio_format_t req_format = config->format;
7877 audio_channel_mask_t req_channel_mask = config->channel_mask;
7878 uint32_t req_sample_rate = config->sample_rate;
7879
7880 pthread_mutex_lock(&adev->lock);
7881 if (is_hdmi) {
7882 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7883 ret = read_hdmi_sink_caps(out);
7884 if (config->sample_rate == 0)
7885 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7886 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7887 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7888 if (config->format == AUDIO_FORMAT_DEFAULT)
7889 config->format = AUDIO_FORMAT_PCM_16_BIT;
7890 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007891 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7892 &config->format,
7893 &out->supported_formats[0],
7894 MAX_SUPPORTED_FORMATS,
7895 &config->channel_mask,
7896 &out->supported_channel_masks[0],
7897 MAX_SUPPORTED_CHANNEL_MASKS,
7898 &config->sample_rate,
7899 &out->supported_sample_rates[0],
7900 MAX_SUPPORTED_SAMPLE_RATES);
7901 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007902 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007903
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007904 pthread_mutex_unlock(&adev->lock);
7905 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007906 if (ret == -ENOSYS) {
7907 /* ignore and go with default */
7908 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007909 }
7910 // For MMAP NO IRQ, allow conversions in ADSP
7911 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7912 goto error_open;
7913 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007914 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007915 goto error_open;
7916 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007917
7918 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7919 config->sample_rate = req_sample_rate;
7920 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7921 config->channel_mask = req_channel_mask;
7922 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7923 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007924 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007925
7926 out->sample_rate = config->sample_rate;
7927 out->channel_mask = config->channel_mask;
7928 out->format = config->format;
7929 if (is_hdmi) {
7930 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7931 out->config = pcm_config_hdmi_multi;
7932 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7933 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7934 out->config = pcm_config_mmap_playback;
7935 out->stream.start = out_start;
7936 out->stream.stop = out_stop;
7937 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7938 out->stream.get_mmap_position = out_get_mmap_position;
7939 } else {
7940 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7941 out->config = pcm_config_hifi;
7942 }
7943
7944 out->config.rate = out->sample_rate;
7945 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7946 if (is_hdmi) {
7947 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7948 audio_bytes_per_sample(out->format));
7949 }
7950 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007951 }
7952
Derek Chenf6318be2017-06-12 17:16:24 -04007953 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007954 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007955 /* extract car audio stream index */
7956 out->car_audio_stream =
7957 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7958 if (out->car_audio_stream < 0) {
7959 ALOGE("%s: invalid car audio stream %x",
7960 __func__, out->car_audio_stream);
7961 ret = -EINVAL;
7962 goto error_open;
7963 }
Derek Chen5f67a942020-02-24 23:08:13 -08007964 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007965 }
7966
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007967 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007968 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007969 if (!voice_extn_is_compress_voip_supported()) {
7970 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7971 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007972 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307973 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007974 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7975 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007976 out->volume_l = INVALID_OUT_VOLUME;
7977 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007978
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007979 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007980 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007981 uint32_t channel_count =
7982 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307983 out->config.channels = channel_count;
7984
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007985 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7986 out->sample_rate, out->format,
7987 channel_count, false);
7988 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7989 if (frame_size != 0)
7990 out->config.period_size = buffer_size / frame_size;
7991 else
7992 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007993 }
7994 } else {
7995 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7996 voice_extn_compress_voip_is_active(out->dev)) &&
7997 (voice_extn_compress_voip_is_config_supported(config))) {
7998 ret = voice_extn_compress_voip_open_output_stream(out);
7999 if (ret != 0) {
8000 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8001 __func__, ret);
8002 goto error_open;
8003 }
Sujin Panicker19027262019-09-16 18:28:06 +05308004 } else {
8005 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8006 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008007 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008008 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008009 } else if (audio_is_linear_pcm(out->format) &&
8010 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8011 out->channel_mask = config->channel_mask;
8012 out->sample_rate = config->sample_rate;
8013 out->format = config->format;
8014 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8015 // does this change?
8016 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8017 out->config.rate = config->sample_rate;
8018 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8019 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8020 audio_bytes_per_sample(config->format));
8021 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008022 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308023 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308024 pthread_mutex_lock(&adev->lock);
8025 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8026 pthread_mutex_unlock(&adev->lock);
8027
8028 // reject offload during card offline to allow
8029 // fallback to s/w paths
8030 if (offline) {
8031 ret = -ENODEV;
8032 goto error_open;
8033 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008034
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008035 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8036 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8037 ALOGE("%s: Unsupported Offload information", __func__);
8038 ret = -EINVAL;
8039 goto error_open;
8040 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008041
Atul Khare3fa6e542017-08-09 00:56:17 +05308042 if (config->offload_info.format == 0)
8043 config->offload_info.format = config->format;
8044 if (config->offload_info.sample_rate == 0)
8045 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008046
Mingming Yin90310102013-11-13 16:57:00 -08008047 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308048 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008049 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 ret = -EINVAL;
8051 goto error_open;
8052 }
8053
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008054 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8055 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8056 (audio_extn_passthru_is_passthrough_stream(out)) &&
8057 !((config->sample_rate == 48000) ||
8058 (config->sample_rate == 96000) ||
8059 (config->sample_rate == 192000))) {
8060 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8061 __func__, config->sample_rate, config->offload_info.format);
8062 ret = -EINVAL;
8063 goto error_open;
8064 }
8065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008066 out->compr_config.codec = (struct snd_codec *)
8067 calloc(1, sizeof(struct snd_codec));
8068
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008069 if (!out->compr_config.codec) {
8070 ret = -ENOMEM;
8071 goto error_open;
8072 }
8073
Dhananjay Kumarac341582017-02-23 23:42:25 +05308074 out->stream.pause = out_pause;
8075 out->stream.resume = out_resume;
8076 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308077 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308078 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008079 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308080 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008081 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308082 } else {
8083 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8084 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008085 }
vivek mehta446c3962015-09-14 10:57:35 -07008086
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308087 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8088 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008089#ifdef AUDIO_GKI_ENABLED
8090 /* out->compr_config.codec->reserved[1] is for flags */
8091 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8092#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308093 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008094#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308095 }
8096
vivek mehta446c3962015-09-14 10:57:35 -07008097 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008098 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008099 config->format == 0 && config->sample_rate == 0 &&
8100 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008101 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008102 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8103 } else {
8104 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8105 ret = -EEXIST;
8106 goto error_open;
8107 }
vivek mehta446c3962015-09-14 10:57:35 -07008108 }
8109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008110 if (config->offload_info.channel_mask)
8111 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008112 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008113 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008114 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008115 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308116 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008117 ret = -EINVAL;
8118 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008119 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008120
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008121 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008122 out->sample_rate = config->offload_info.sample_rate;
8123
Mingming Yin3ee55c62014-08-04 14:23:35 -07008124 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008125
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308126 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308127 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308128 audio_extn_dolby_send_ddp_endp_params(adev);
8129 audio_extn_dolby_set_dmid(adev);
8130 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008132 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008133 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008134 out->compr_config.codec->bit_rate =
8135 config->offload_info.bit_rate;
8136 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308137 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008138 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308139 /* Update bit width only for non passthrough usecases.
8140 * For passthrough usecases, the output will always be opened @16 bit
8141 */
8142 if (!audio_extn_passthru_is_passthrough_stream(out))
8143 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308144
8145 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008146#ifdef AUDIO_GKI_ENABLED
8147 /* out->compr_config.codec->reserved[1] is for flags */
8148 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8149 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8150#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308151 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8152 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008153#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308154
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008155 /*TODO: Do we need to change it for passthrough */
8156 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008157
Manish Dewangana6fc5442015-08-24 20:30:31 +05308158 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8159 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308160 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308161 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308162 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8163 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308164
8165 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8166 AUDIO_FORMAT_PCM) {
8167
8168 /*Based on platform support, configure appropriate alsa format for corresponding
8169 *hal input format.
8170 */
8171 out->compr_config.codec->format = hal_format_to_alsa(
8172 config->offload_info.format);
8173
Ashish Jain83a6cc22016-06-28 14:34:17 +05308174 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308175 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308176 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308177
Dhananjay Kumarac341582017-02-23 23:42:25 +05308178 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308179 *hal input format and alsa format might differ based on platform support.
8180 */
8181 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308182 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308183
8184 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8185
Deeraj Soman93155a62019-09-30 19:00:37 +05308186 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8187 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8188 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8189 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8190 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308191
Ashish Jainf1eaa582016-05-23 20:54:24 +05308192 /* Check if alsa session is configured with the same format as HAL input format,
8193 * if not then derive correct fragment size needed to accomodate the
8194 * conversion of HAL input format to alsa format.
8195 */
8196 audio_extn_utils_update_direct_pcm_fragment_size(out);
8197
8198 /*if hal input and output fragment size is different this indicates HAL input format is
8199 *not same as the alsa format
8200 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308201 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308202 /*Allocate a buffer to convert input data to the alsa configured format.
8203 *size of convert buffer is equal to the size required to hold one fragment size
8204 *worth of pcm data, this is because flinger does not write more than fragment_size
8205 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308206 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8207 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308208 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8209 ret = -ENOMEM;
8210 goto error_open;
8211 }
8212 }
8213 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8214 out->compr_config.fragment_size =
8215 audio_extn_passthru_get_buffer_size(&config->offload_info);
8216 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8217 } else {
8218 out->compr_config.fragment_size =
8219 platform_get_compress_offload_buffer_size(&config->offload_info);
8220 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8221 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008222
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308223 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8224 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8225 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008226 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8227#ifdef AUDIO_GKI_ENABLED
8228 generic_dec =
8229 &(out->compr_config.codec->options.generic.reserved[1]);
8230 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8231 AUDIO_OUTPUT_BIT_WIDTH;
8232#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308233 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008234#endif
8235 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008236
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308237 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8238 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8239 }
8240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008241 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8242 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008243
Manish Dewangan69426c82017-01-30 17:35:36 +05308244 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8245 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8246 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8247 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8248 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8249 } else {
8250 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8251 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008252
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308253 memset(&out->channel_map_param, 0,
8254 sizeof(struct audio_out_channel_map_param));
8255
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008256 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308257 out->send_next_track_params = false;
8258 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008259 out->offload_state = OFFLOAD_STATE_IDLE;
8260 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008261 out->writeAt.tv_sec = 0;
8262 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008263
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008264 audio_extn_dts_create_state_notifier_node(out->usecase);
8265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008266 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8267 __func__, config->offload_info.version,
8268 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308269
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308270 /* Check if DSD audio format is supported in codec
8271 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308272 */
8273
8274 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308275 (!platform_check_codec_dsd_support(adev->platform) ||
8276 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308277 ret = -EINVAL;
8278 goto error_open;
8279 }
8280
Ashish Jain5106d362016-05-11 19:23:33 +05308281 /* Disable gapless if any of the following is true
8282 * passthrough playback
8283 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308284 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308285 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308286 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308287 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008288 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308289 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308290 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308291 check_and_set_gapless_mode(adev, false);
8292 } else
8293 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008294
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308295 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008296 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8297 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308298 if (config->format == AUDIO_FORMAT_DSD) {
8299 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008300#ifdef AUDIO_GKI_ENABLED
8301 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8302 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8303#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308304 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008305#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308306 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008307
8308 create_offload_callback_thread(out);
8309
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008310 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008311 switch (config->sample_rate) {
8312 case 0:
8313 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8314 break;
8315 case 8000:
8316 case 16000:
8317 case 48000:
8318 out->sample_rate = config->sample_rate;
8319 break;
8320 default:
8321 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8322 config->sample_rate);
8323 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8324 ret = -EINVAL;
8325 goto error_open;
8326 }
8327 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8328 switch (config->channel_mask) {
8329 case AUDIO_CHANNEL_NONE:
8330 case AUDIO_CHANNEL_OUT_STEREO:
8331 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8332 break;
8333 default:
8334 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8335 config->channel_mask);
8336 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8337 ret = -EINVAL;
8338 goto error_open;
8339 }
8340 switch (config->format) {
8341 case AUDIO_FORMAT_DEFAULT:
8342 case AUDIO_FORMAT_PCM_16_BIT:
8343 out->format = AUDIO_FORMAT_PCM_16_BIT;
8344 break;
8345 default:
8346 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8347 config->format);
8348 config->format = AUDIO_FORMAT_PCM_16_BIT;
8349 ret = -EINVAL;
8350 goto error_open;
8351 }
8352
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308353 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008354 if (ret != 0) {
8355 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008356 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008357 goto error_open;
8358 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008359 } else if (is_single_device_type_equal(&out->device_list,
8360 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008361 switch (config->sample_rate) {
8362 case 0:
8363 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8364 break;
8365 case 8000:
8366 case 16000:
8367 case 48000:
8368 out->sample_rate = config->sample_rate;
8369 break;
8370 default:
8371 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8372 config->sample_rate);
8373 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8374 ret = -EINVAL;
8375 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008376 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008377 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8378 switch (config->channel_mask) {
8379 case AUDIO_CHANNEL_NONE:
8380 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8381 break;
8382 case AUDIO_CHANNEL_OUT_STEREO:
8383 out->channel_mask = config->channel_mask;
8384 break;
8385 default:
8386 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8387 config->channel_mask);
8388 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8389 ret = -EINVAL;
8390 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008391 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008392 switch (config->format) {
8393 case AUDIO_FORMAT_DEFAULT:
8394 out->format = AUDIO_FORMAT_PCM_16_BIT;
8395 break;
8396 case AUDIO_FORMAT_PCM_16_BIT:
8397 out->format = config->format;
8398 break;
8399 default:
8400 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8401 config->format);
8402 config->format = AUDIO_FORMAT_PCM_16_BIT;
8403 ret = -EINVAL;
8404 break;
8405 }
8406 if (ret != 0)
8407 goto error_open;
8408
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008409 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8410 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008411 out->config.rate = out->sample_rate;
8412 out->config.channels =
8413 audio_channel_count_from_out_mask(out->channel_mask);
8414 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008415 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008416 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308417 unsigned int channels = 0;
8418 /*Update config params to default if not set by the caller*/
8419 if (config->sample_rate == 0)
8420 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8421 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8422 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8423 if (config->format == AUDIO_FORMAT_DEFAULT)
8424 config->format = AUDIO_FORMAT_PCM_16_BIT;
8425
8426 channels = audio_channel_count_from_out_mask(out->channel_mask);
8427
Varun Balaraje49253e2017-07-06 19:48:56 +05308428 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8429 out->usecase = get_interactive_usecase(adev);
8430 out->config = pcm_config_low_latency;
8431 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308432 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008433 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8434 out->flags);
8435 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008436 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8437 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8438 out->config = pcm_config_mmap_playback;
8439 out->stream.start = out_start;
8440 out->stream.stop = out_stop;
8441 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8442 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308443 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8444 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008445 out->hal_output_suspend_supported =
8446 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8447 out->dynamic_pm_qos_config_supported =
8448 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8449 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008450 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8451 } else {
8452 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8453 //the mixer path will be a string similar to "low-latency-playback resume"
8454 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8455 strlcat(out->pm_qos_mixer_path,
8456 " resume", MAX_MIXER_PATH_LEN);
8457 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8458 out->pm_qos_mixer_path);
8459 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308460 out->config = pcm_config_low_latency;
8461 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8462 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8463 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308464 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8465 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8466 if (out->config.period_size <= 0) {
8467 ALOGE("Invalid configuration period size is not valid");
8468 ret = -EINVAL;
8469 goto error_open;
8470 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008471 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8472 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8473 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008474 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8475 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8476 out->config = pcm_config_haptics_audio;
8477 if (force_haptic_path)
8478 adev->haptics_config = pcm_config_haptics_audio;
8479 else
8480 adev->haptics_config = pcm_config_haptics;
8481
Meng Wangd08ce322020-04-02 08:59:20 +08008482 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008483 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8484
8485 if (force_haptic_path) {
8486 out->config.channels = 1;
8487 adev->haptics_config.channels = 1;
8488 } else
8489 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 -08008490 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008491 ret = audio_extn_auto_hal_open_output_stream(out);
8492 if (ret) {
8493 ALOGE("%s: Failed to open output stream for bus device", __func__);
8494 ret = -EINVAL;
8495 goto error_open;
8496 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308497 } else {
8498 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008499 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8500 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308501 }
8502 out->hal_ip_format = format = out->format;
8503 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8504 out->hal_op_format = pcm_format_to_hal(out->config.format);
8505 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8506 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008507 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308508 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308509 if (out->hal_ip_format != out->hal_op_format) {
8510 uint32_t buffer_size = out->config.period_size *
8511 format_to_bitwidth_table[out->hal_op_format] *
8512 out->config.channels;
8513 out->convert_buffer = calloc(1, buffer_size);
8514 if (out->convert_buffer == NULL){
8515 ALOGE("Allocation failed for convert buffer for size %d",
8516 out->compr_config.fragment_size);
8517 ret = -ENOMEM;
8518 goto error_open;
8519 }
8520 ALOGD("Convert buffer allocated of size %d", buffer_size);
8521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008522 }
8523
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008524 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8525 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308526
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008527 /* TODO remove this hardcoding and check why width is zero*/
8528 if (out->bit_width == 0)
8529 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308530 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008531 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008532 &out->device_list, out->flags,
8533 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308534 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308535 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008536 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008537 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8538 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008539 if(adev->primary_output == NULL)
8540 adev->primary_output = out;
8541 else {
8542 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008543 ret = -EEXIST;
8544 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008545 }
8546 }
8547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008548 /* Check if this usecase is already existing */
8549 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008550 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8551 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008553 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008554 ret = -EEXIST;
8555 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008556 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008558 pthread_mutex_unlock(&adev->lock);
8559
8560 out->stream.common.get_sample_rate = out_get_sample_rate;
8561 out->stream.common.set_sample_rate = out_set_sample_rate;
8562 out->stream.common.get_buffer_size = out_get_buffer_size;
8563 out->stream.common.get_channels = out_get_channels;
8564 out->stream.common.get_format = out_get_format;
8565 out->stream.common.set_format = out_set_format;
8566 out->stream.common.standby = out_standby;
8567 out->stream.common.dump = out_dump;
8568 out->stream.common.set_parameters = out_set_parameters;
8569 out->stream.common.get_parameters = out_get_parameters;
8570 out->stream.common.add_audio_effect = out_add_audio_effect;
8571 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8572 out->stream.get_latency = out_get_latency;
8573 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008574#ifdef NO_AUDIO_OUT
8575 out->stream.write = out_write_for_no_output;
8576#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008577 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008578#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008579 out->stream.get_render_position = out_get_render_position;
8580 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008581 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008582
Haynes Mathew George16081042017-05-31 17:16:49 -07008583 if (out->realtime)
8584 out->af_period_multiplier = af_period_multiplier;
8585 else
8586 out->af_period_multiplier = 1;
8587
Andy Hunga1f48fa2019-07-01 18:14:53 -07008588 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008590 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008591 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008592 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008593
8594 config->format = out->stream.common.get_format(&out->stream.common);
8595 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8596 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308597 register_format(out->format, out->supported_formats);
8598 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8599 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008600
Aalique Grahame22e49102018-12-18 14:23:57 -08008601 out->error_log = error_log_create(
8602 ERROR_LOG_ENTRIES,
8603 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8604
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308605 /*
8606 By locking output stream before registering, we allow the callback
8607 to update stream's state only after stream's initial state is set to
8608 adev state.
8609 */
8610 lock_output_stream(out);
8611 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8612 pthread_mutex_lock(&adev->lock);
8613 out->card_status = adev->card_status;
8614 pthread_mutex_unlock(&adev->lock);
8615 pthread_mutex_unlock(&out->lock);
8616
Aalique Grahame22e49102018-12-18 14:23:57 -08008617 stream_app_type_cfg_init(&out->app_type_cfg);
8618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008619 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308620 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008621 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008622
8623 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8624 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8625 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008626 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308627 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008628 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008629 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308630 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8631 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008632 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8633 out->usecase, PCM_PLAYBACK);
8634 hdlr_stream_cfg.flags = out->flags;
8635 hdlr_stream_cfg.type = PCM_PLAYBACK;
8636 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8637 &hdlr_stream_cfg);
8638 if (ret) {
8639 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8640 out->adsp_hdlr_stream_handle = NULL;
8641 }
8642 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308643 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8644 is_direct_passthough, false);
8645 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8646 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008647 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008648 if (ret < 0) {
8649 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8650 out->ip_hdlr_handle = NULL;
8651 }
8652 }
Derek Chenf939fb72018-11-13 13:34:41 -08008653
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008654 ret = io_streams_map_insert(adev, &out->stream.common,
8655 out->handle, AUDIO_PATCH_HANDLE_NONE);
8656 if (ret != 0)
8657 goto error_open;
8658
Derek Chenf939fb72018-11-13 13:34:41 -08008659 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8660 calloc(1, sizeof(streams_output_ctxt_t));
8661 if (out_ctxt == NULL) {
8662 ALOGE("%s fail to allocate output ctxt", __func__);
8663 ret = -ENOMEM;
8664 goto error_open;
8665 }
8666 out_ctxt->output = out;
8667
8668 pthread_mutex_lock(&adev->lock);
8669 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8670 pthread_mutex_unlock(&adev->lock);
8671
Eric Laurent994a6932013-07-17 11:51:42 -07008672 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008673 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008674
8675error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308676 if (out->convert_buffer)
8677 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008678 free(out);
8679 *stream_out = NULL;
8680 ALOGD("%s: exit: ret %d", __func__, ret);
8681 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008682}
8683
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308684void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008685 struct audio_stream_out *stream)
8686{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008687 struct stream_out *out = (struct stream_out *)stream;
8688 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008689 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008690
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008691 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308692
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008693 io_streams_map_remove(adev, out->handle);
8694
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308695 // must deregister from sndmonitor first to prevent races
8696 // between the callback and close_stream
8697 audio_extn_snd_mon_unregister_listener(out);
8698
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008699 /* close adsp hdrl session before standby */
8700 if (out->adsp_hdlr_stream_handle) {
8701 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8702 if (ret)
8703 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8704 out->adsp_hdlr_stream_handle = NULL;
8705 }
8706
Manish Dewangan21a850a2017-08-14 12:03:55 +05308707 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008708 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8709 out->ip_hdlr_handle = NULL;
8710 }
8711
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008712 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308713 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008714 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308715 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308716 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008717 if(ret != 0)
8718 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8719 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008720 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008721 out_standby(&stream->common);
8722
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008723 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008724 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008725 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008726 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008727 if (out->compr_config.codec != NULL)
8728 free(out->compr_config.codec);
8729 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008730
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308731 out->a2dp_compress_mute = false;
8732
Varun Balaraje49253e2017-07-06 19:48:56 +05308733 if (is_interactive_usecase(out->usecase))
8734 free_interactive_usecase(adev, out->usecase);
8735
Ashish Jain83a6cc22016-06-28 14:34:17 +05308736 if (out->convert_buffer != NULL) {
8737 free(out->convert_buffer);
8738 out->convert_buffer = NULL;
8739 }
8740
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008741 if (adev->voice_tx_output == out)
8742 adev->voice_tx_output = NULL;
8743
Aalique Grahame22e49102018-12-18 14:23:57 -08008744 error_log_destroy(out->error_log);
8745 out->error_log = NULL;
8746
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308747 if (adev->primary_output == out)
8748 adev->primary_output = NULL;
8749
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008750 pthread_cond_destroy(&out->cond);
8751 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008752 pthread_mutex_destroy(&out->pre_lock);
8753 pthread_mutex_destroy(&out->latch_lock);
8754 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008755
8756 pthread_mutex_lock(&adev->lock);
8757 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8758 if (out_ctxt != NULL) {
8759 list_remove(&out_ctxt->list);
8760 free(out_ctxt);
8761 } else {
8762 ALOGW("%s, output stream already closed", __func__);
8763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008764 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008765 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008766 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008767}
8768
8769static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8770{
8771 struct audio_device *adev = (struct audio_device *)dev;
8772 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008773 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008774 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008775 int ret;
8776 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008777 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008778 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008779 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008780
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008781 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008783
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308784 if (!parms)
8785 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308786
Derek Chen6f293672019-04-01 01:40:24 -07008787 /* notify adev and input/output streams on the snd card status */
8788 adev_snd_mon_cb((void *)adev, parms);
8789
8790 list_for_each(node, &adev->active_outputs_list) {
8791 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8792 streams_output_ctxt_t,
8793 list);
8794 out_snd_mon_cb((void *)out_ctxt->output, parms);
8795 }
8796
8797 list_for_each(node, &adev->active_inputs_list) {
8798 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8799 streams_input_ctxt_t,
8800 list);
8801 in_snd_mon_cb((void *)in_ctxt->input, parms);
8802 }
8803
Zhou Songd6d71752019-05-21 18:08:51 +08008804 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308805 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8806 if (ret >= 0) {
8807 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008808 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308809 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008810 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308811 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008812 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008813 }
8814 }
8815
8816 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008817 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008818 if (!strncmp(value, "false", 5) &&
8819 audio_extn_a2dp_source_is_suspended()) {
8820 struct audio_usecase *usecase;
8821 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008822 list_for_each(node, &adev->usecase_list) {
8823 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008824 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008825 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008826 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008827 reassign_device_list(&usecase->stream.in->device_list,
8828 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008829 select_devices(adev, usecase->id);
8830 }
Zhou Songd6d71752019-05-21 18:08:51 +08008831 }
8832 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308833 }
8834
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008835 status = voice_set_parameters(adev, parms);
8836 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008837 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008838
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008839 status = platform_set_parameters(adev->platform, parms);
8840 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008841 goto done;
8842
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008843 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8844 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008845 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008846 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8847 adev->bluetooth_nrec = true;
8848 else
8849 adev->bluetooth_nrec = false;
8850 }
8851
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008852 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8853 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008854 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8855 adev->screen_off = false;
8856 else
8857 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008858 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008859 }
8860
Eric Laurent4b084132018-10-19 17:33:43 -07008861 ret = str_parms_get_int(parms, "rotation", &val);
8862 if (ret >= 0) {
8863 bool reverse_speakers = false;
8864 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8865 switch (val) {
8866 // FIXME: note that the code below assumes that the speakers are in the correct placement
8867 // relative to the user when the device is rotated 90deg from its default rotation. This
8868 // assumption is device-specific, not platform-specific like this code.
8869 case 270:
8870 reverse_speakers = true;
8871 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8872 break;
8873 case 0:
8874 case 180:
8875 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8876 break;
8877 case 90:
8878 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8879 break;
8880 default:
8881 ALOGE("%s: unexpected rotation of %d", __func__, val);
8882 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008883 }
Eric Laurent4b084132018-10-19 17:33:43 -07008884 if (status == 0) {
8885 // check and set swap
8886 // - check if orientation changed and speaker active
8887 // - set rotation and cache the rotation value
8888 adev->camera_orientation =
8889 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8890 if (!audio_extn_is_maxx_audio_enabled())
8891 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8892 }
8893 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008894
Mingming Yin514a8bc2014-07-29 15:22:21 -07008895 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8896 if (ret >= 0) {
8897 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8898 adev->bt_wb_speech_enabled = true;
8899 else
8900 adev->bt_wb_speech_enabled = false;
8901 }
8902
Zhou Song12c29502019-03-16 10:37:18 +08008903 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8904 if (ret >= 0) {
8905 val = atoi(value);
8906 adev->swb_speech_mode = val;
8907 }
8908
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008909 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8910 if (ret >= 0) {
8911 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308912 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008913 if (audio_is_output_device(val) &&
8914 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008915 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008916 platform_get_controller_stream_from_params(parms, &controller, &stream);
8917 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8918 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008919 if (ret < 0) {
8920 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308921 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008922 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008923 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308924 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008925 /*
8926 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8927 * Per AudioPolicyManager, USB device is higher priority than WFD.
8928 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8929 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8930 * starting voice call on USB
8931 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008932 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308933 if (ret >= 0)
8934 audio_extn_usb_add_device(device, atoi(value));
8935
Zhou Song6f862822017-11-06 17:27:57 +08008936 if (!audio_extn_usb_is_tunnel_supported()) {
8937 ALOGV("detected USB connect .. disable proxy");
8938 adev->allow_afe_proxy_usage = false;
8939 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008940 }
8941 }
8942
8943 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8944 if (ret >= 0) {
8945 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308946 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008947 /*
8948 * The HDMI / Displayport disconnect handling has been moved to
8949 * audio extension to ensure that its parameters are not
8950 * invalidated prior to updating sysfs of the disconnect event
8951 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8952 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308953 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008954 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308955 if (ret >= 0)
8956 audio_extn_usb_remove_device(device, atoi(value));
8957
Zhou Song6f862822017-11-06 17:27:57 +08008958 if (!audio_extn_usb_is_tunnel_supported()) {
8959 ALOGV("detected USB disconnect .. enable proxy");
8960 adev->allow_afe_proxy_usage = true;
8961 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008962 }
8963 }
8964
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008965 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008966
8967 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008968 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308969 struct audio_usecase *usecase;
8970 struct listnode *node;
8971 list_for_each(node, &adev->usecase_list) {
8972 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008973 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8974 continue;
8975
8976 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308977 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308978 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308979 ALOGD("Switching to speaker and muting the stream before select_devices");
8980 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308981 //force device switch to re configure encoder
8982 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308983 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiang280ea742020-09-08 20:28:22 +08008984 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308985 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiang280ea742020-09-08 20:28:22 +08008986 out_set_compr_volume(&usecase->stream.out->stream,
8987 usecase->stream.out->volume_l,
8988 usecase->stream.out->volume_r);
8989 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308990 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308991 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008992 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008993 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8994 if (usecase->stream.out->a2dp_compress_mute) {
8995 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8996 reassign_device_list(&usecase->stream.out->device_list,
8997 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8998 check_a2dp_restore_l(adev, usecase->stream.out, true);
8999 break;
9000 }
9001 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309002 }
9003 }
9004 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009005
9006 //handle vr audio setparam
9007 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9008 value, sizeof(value));
9009 if (ret >= 0) {
9010 ALOGI("Setting vr mode to be %s", value);
9011 if (!strncmp(value, "true", 4)) {
9012 adev->vr_audio_mode_enabled = true;
9013 ALOGI("Setting vr mode to true");
9014 } else if (!strncmp(value, "false", 5)) {
9015 adev->vr_audio_mode_enabled = false;
9016 ALOGI("Setting vr mode to false");
9017 } else {
9018 ALOGI("wrong vr mode set");
9019 }
9020 }
9021
Eric Laurent4b084132018-10-19 17:33:43 -07009022 //FIXME: to be replaced by proper video capture properties API
9023 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9024 if (ret >= 0) {
9025 int camera_facing = CAMERA_FACING_BACK;
9026 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9027 camera_facing = CAMERA_FACING_FRONT;
9028 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9029 camera_facing = CAMERA_FACING_BACK;
9030 else {
9031 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9032 goto done;
9033 }
9034 adev->camera_orientation =
9035 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9036 struct audio_usecase *usecase;
9037 struct listnode *node;
9038 list_for_each(node, &adev->usecase_list) {
9039 usecase = node_to_item(node, struct audio_usecase, list);
9040 struct stream_in *in = usecase->stream.in;
9041 if (usecase->type == PCM_CAPTURE && in != NULL &&
9042 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9043 select_devices(adev, in->usecase);
9044 }
9045 }
9046 }
9047
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309048 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009049done:
9050 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009051 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309052error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009053 ALOGV("%s: exit with code(%d)", __func__, status);
9054 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009055}
9056
9057static char* adev_get_parameters(const struct audio_hw_device *dev,
9058 const char *keys)
9059{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309060 ALOGD("%s:%s", __func__, keys);
9061
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009062 struct audio_device *adev = (struct audio_device *)dev;
9063 struct str_parms *reply = str_parms_create();
9064 struct str_parms *query = str_parms_create_str(keys);
9065 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309066 char value[256] = {0};
9067 int ret = 0;
9068
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009069 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009070 if (reply) {
9071 str_parms_destroy(reply);
9072 }
9073 if (query) {
9074 str_parms_destroy(query);
9075 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009076 ALOGE("adev_get_parameters: failed to create query or reply");
9077 return NULL;
9078 }
9079
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009080 //handle vr audio getparam
9081
9082 ret = str_parms_get_str(query,
9083 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9084 value, sizeof(value));
9085
9086 if (ret >= 0) {
9087 bool vr_audio_enabled = false;
9088 pthread_mutex_lock(&adev->lock);
9089 vr_audio_enabled = adev->vr_audio_mode_enabled;
9090 pthread_mutex_unlock(&adev->lock);
9091
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009092 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009093
9094 if (vr_audio_enabled) {
9095 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9096 "true");
9097 goto exit;
9098 } else {
9099 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9100 "false");
9101 goto exit;
9102 }
9103 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009104
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009105 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009106 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009107 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009108 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009109 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009110 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309111 pthread_mutex_unlock(&adev->lock);
9112
Naresh Tannirud7205b62014-06-20 02:54:48 +05309113exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009114 str = str_parms_to_str(reply);
9115 str_parms_destroy(query);
9116 str_parms_destroy(reply);
9117
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009118 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009119 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009120}
9121
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009122static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123{
9124 return 0;
9125}
9126
9127static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9128{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009129 int ret;
9130 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009131
9132 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9133
Haynes Mathew George5191a852013-09-11 14:19:36 -07009134 pthread_mutex_lock(&adev->lock);
9135 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009136 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009137 pthread_mutex_unlock(&adev->lock);
9138 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009139}
9140
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009141static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9142 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009143{
9144 return -ENOSYS;
9145}
9146
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009147static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9148 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149{
9150 return -ENOSYS;
9151}
9152
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009153static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9154 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009155{
9156 return -ENOSYS;
9157}
9158
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009159static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9160 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009161{
9162 return -ENOSYS;
9163}
9164
9165static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9166{
9167 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009168 struct listnode *node;
9169 struct audio_usecase *usecase = NULL;
9170 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172 pthread_mutex_lock(&adev->lock);
9173 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309174 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9175 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009177 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309178 adev->current_call_output = adev->primary_output;
9179 voice_start_call(adev);
9180 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009181 (mode == AUDIO_MODE_NORMAL ||
9182 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009183 list_for_each(node, &adev->usecase_list) {
9184 usecase = node_to_item(node, struct audio_usecase, list);
9185 if (usecase->type == VOICE_CALL)
9186 break;
9187 }
9188 if (usecase &&
9189 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9190 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9191 true);
9192 if (ret != 0) {
9193 /* default service interval was successfully updated,
9194 reopen USB backend with new service interval */
9195 check_usecases_codec_backend(adev,
9196 usecase,
9197 usecase->out_snd_device);
9198 }
9199 }
9200
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009201 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009202 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009203 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009204 // restore device for other active usecases after stop call
9205 list_for_each(node, &adev->usecase_list) {
9206 usecase = node_to_item(node, struct audio_usecase, list);
9207 select_devices(adev, usecase->id);
9208 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009209 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009210 }
9211 pthread_mutex_unlock(&adev->lock);
9212 return 0;
9213}
9214
9215static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9216{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009217 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009218 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009219
9220 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009221 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009222 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009223
Derek Chend2530072014-11-24 12:39:14 -08009224 if (adev->ext_hw_plugin)
9225 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009226
9227 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009228 pthread_mutex_unlock(&adev->lock);
9229
9230 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231}
9232
9233static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9234{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009235 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236 return 0;
9237}
9238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009239static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009240 const struct audio_config *config)
9241{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009242 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009243
Aalique Grahame22e49102018-12-18 14:23:57 -08009244 /* Don't know if USB HIFI in this context so use true to be conservative */
9245 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9246 true /*is_usb_hifi */) != 0)
9247 return 0;
9248
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009249 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9250 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009251}
9252
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009253static bool adev_input_allow_hifi_record(struct audio_device *adev,
9254 audio_devices_t devices,
9255 audio_input_flags_t flags,
9256 audio_source_t source) {
9257 const bool allowed = true;
9258
9259 if (!audio_is_usb_in_device(devices))
9260 return !allowed;
9261
9262 switch (flags) {
9263 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009264 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009265 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9266 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009267 default:
9268 return !allowed;
9269 }
9270
9271 switch (source) {
9272 case AUDIO_SOURCE_DEFAULT:
9273 case AUDIO_SOURCE_MIC:
9274 case AUDIO_SOURCE_UNPROCESSED:
9275 break;
9276 default:
9277 return !allowed;
9278 }
9279
9280 switch (adev->mode) {
9281 case 0:
9282 break;
9283 default:
9284 return !allowed;
9285 }
9286
9287 return allowed;
9288}
9289
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009290static int adev_update_voice_comm_input_stream(struct stream_in *in,
9291 struct audio_config *config)
9292{
9293 bool valid_rate = (config->sample_rate == 8000 ||
9294 config->sample_rate == 16000 ||
9295 config->sample_rate == 32000 ||
9296 config->sample_rate == 48000);
9297 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9298
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009299 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009300 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009301 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9302 in->config = default_pcm_config_voip_copp;
9303 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9304 DEFAULT_VOIP_BUF_DURATION_MS,
9305 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009306 } else {
9307 ALOGW("%s No valid input in voip, use defaults"
9308 "sample rate %u, channel mask 0x%X",
9309 __func__, config->sample_rate, in->channel_mask);
9310 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009311 in->config.rate = config->sample_rate;
9312 in->sample_rate = config->sample_rate;
9313 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009314 //XXX needed for voice_extn_compress_voip_open_input_stream
9315 in->config.rate = config->sample_rate;
9316 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309317 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009318 voice_extn_compress_voip_is_active(in->dev)) &&
9319 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9320 valid_rate && valid_ch) {
9321 voice_extn_compress_voip_open_input_stream(in);
9322 // update rate entries to match config from AF
9323 in->config.rate = config->sample_rate;
9324 in->sample_rate = config->sample_rate;
9325 } else {
9326 ALOGW("%s compress voip not active, use defaults", __func__);
9327 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009328 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009329 return 0;
9330}
9331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009332static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009333 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009334 audio_devices_t devices,
9335 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009336 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309337 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009338 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009339 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009340{
9341 struct audio_device *adev = (struct audio_device *)dev;
9342 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009343 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009344 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009345 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309346 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009347 bool is_usb_dev = audio_is_usb_in_device(devices);
9348 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9349 devices,
9350 flags,
9351 source);
Andy Hung94320602018-10-29 18:31:12 -07009352 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9353 " sample_rate %u, channel_mask %#x, format %#x",
9354 __func__, flags, is_usb_dev, may_use_hifi_record,
9355 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309356
kunleizdff872d2018-08-20 14:40:33 +08009357 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009358 is_usb_dev = false;
9359 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9360 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9361 __func__, devices);
9362 }
9363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009364 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009365
9366 if (!(is_usb_dev && may_use_hifi_record)) {
9367 if (config->sample_rate == 0)
9368 config->sample_rate = 48000;
9369 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9370 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9371 if (config->format == AUDIO_FORMAT_DEFAULT)
9372 config->format = AUDIO_FORMAT_PCM_16_BIT;
9373
9374 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9375
Aalique Grahame22e49102018-12-18 14:23:57 -08009376 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9377 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009378 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309379 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009380
Rahul Sharma99770982019-03-06 17:05:26 +05309381 pthread_mutex_lock(&adev->lock);
9382 if (in_get_stream(adev, handle) != NULL) {
9383 ALOGW("%s, input stream already opened", __func__);
9384 ret = -EEXIST;
9385 }
9386 pthread_mutex_unlock(&adev->lock);
9387 if (ret)
9388 return ret;
9389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009390 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009391
9392 if (!in) {
9393 ALOGE("failed to allocate input stream");
9394 return -ENOMEM;
9395 }
9396
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309397 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309398 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9399 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009400 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009401 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009403 in->stream.common.get_sample_rate = in_get_sample_rate;
9404 in->stream.common.set_sample_rate = in_set_sample_rate;
9405 in->stream.common.get_buffer_size = in_get_buffer_size;
9406 in->stream.common.get_channels = in_get_channels;
9407 in->stream.common.get_format = in_get_format;
9408 in->stream.common.set_format = in_set_format;
9409 in->stream.common.standby = in_standby;
9410 in->stream.common.dump = in_dump;
9411 in->stream.common.set_parameters = in_set_parameters;
9412 in->stream.common.get_parameters = in_get_parameters;
9413 in->stream.common.add_audio_effect = in_add_audio_effect;
9414 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9415 in->stream.set_gain = in_set_gain;
9416 in->stream.read = in_read;
9417 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009418 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309419 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009420 in->stream.set_microphone_direction = in_set_microphone_direction;
9421 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009422 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009423
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009424 list_init(&in->device_list);
9425 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009426 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009427 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009428 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009429 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009430 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009431 in->bit_width = 16;
9432 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009433 in->direction = MIC_DIRECTION_UNSPECIFIED;
9434 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009435 list_init(&in->aec_list);
9436 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009437 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009438
Andy Hung94320602018-10-29 18:31:12 -07009439 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009440 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9441 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9442 /* Force channel config requested to mono if incall
9443 record is being requested for only uplink/downlink */
9444 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9445 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9446 ret = -EINVAL;
9447 goto err_open;
9448 }
9449 }
9450
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009451 if (is_usb_dev && may_use_hifi_record) {
9452 /* HiFi record selects an appropriate format, channel, rate combo
9453 depending on sink capabilities*/
9454 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9455 &config->format,
9456 &in->supported_formats[0],
9457 MAX_SUPPORTED_FORMATS,
9458 &config->channel_mask,
9459 &in->supported_channel_masks[0],
9460 MAX_SUPPORTED_CHANNEL_MASKS,
9461 &config->sample_rate,
9462 &in->supported_sample_rates[0],
9463 MAX_SUPPORTED_SAMPLE_RATES);
9464 if (ret != 0) {
9465 ret = -EINVAL;
9466 goto err_open;
9467 }
9468 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009469 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309470 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309471 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9472 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9473 in->config.format = PCM_FORMAT_S32_LE;
9474 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309475 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9476 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9477 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9478 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9479 bool ret_error = false;
9480 in->bit_width = 24;
9481 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9482 from HAL is 24_packed and 8_24
9483 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9484 24_packed return error indicating supported format is 24_packed
9485 *> In case of any other source requesting 24 bit or float return error
9486 indicating format supported is 16 bit only.
9487
9488 on error flinger will retry with supported format passed
9489 */
9490 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9491 (source != AUDIO_SOURCE_CAMCORDER)) {
9492 config->format = AUDIO_FORMAT_PCM_16_BIT;
9493 if (config->sample_rate > 48000)
9494 config->sample_rate = 48000;
9495 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009496 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9497 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309498 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9499 ret_error = true;
9500 }
9501
9502 if (ret_error) {
9503 ret = -EINVAL;
9504 goto err_open;
9505 }
9506 }
9507
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009508 in->channel_mask = config->channel_mask;
9509 in->format = config->format;
9510
9511 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309512
Huicheng Liu1404ba12020-09-11 01:03:25 -04009513 /* validate bus device address */
9514 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9515 /* extract car audio stream index */
9516 in->car_audio_stream =
9517 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9518 if (in->car_audio_stream < 0) {
9519 ALOGE("%s: invalid car audio stream %x",
9520 __func__, in->car_audio_stream);
9521 ret = -EINVAL;
9522 goto err_open;
9523 }
9524 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
9525 }
9526
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309527 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9528 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9529 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9530 else {
9531 ret = -EINVAL;
9532 goto err_open;
9533 }
9534 }
9535
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009536 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309537 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9538 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009539 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9540 is_low_latency = true;
9541#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309542 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9543 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9544 else
9545 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009546#endif
9547 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009548 if (!in->realtime) {
9549 in->config = pcm_config_audio_capture;
9550 frame_size = audio_stream_in_frame_size(&in->stream);
9551 buffer_size = get_input_buffer_size(config->sample_rate,
9552 config->format,
9553 channel_count,
9554 is_low_latency);
9555 in->config.period_size = buffer_size / frame_size;
9556 in->config.rate = config->sample_rate;
9557 in->af_period_multiplier = 1;
9558 } else {
9559 // period size is left untouched for rt mode playback
9560 in->config = pcm_config_audio_capture_rt;
9561 in->af_period_multiplier = af_period_multiplier;
9562 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009563 }
9564
9565 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9566 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9567 in->realtime = 0;
9568 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9569 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009570 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009571 in->stream.start = in_start;
9572 in->stream.stop = in_stop;
9573 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9574 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009575 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009576 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009577 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9578 in->config = pcm_config_audio_capture;
9579 frame_size = audio_stream_in_frame_size(&in->stream);
9580 buffer_size = get_input_buffer_size(config->sample_rate,
9581 config->format,
9582 channel_count,
9583 false /*is_low_latency*/);
9584 in->config.period_size = buffer_size / frame_size;
9585 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009586 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009587 switch (config->format) {
9588 case AUDIO_FORMAT_PCM_32_BIT:
9589 in->bit_width = 32;
9590 break;
9591 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9592 case AUDIO_FORMAT_PCM_8_24_BIT:
9593 in->bit_width = 24;
9594 break;
9595 default:
9596 in->bit_width = 16;
9597 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009598 } else if (is_single_device_type_equal(&in->device_list,
9599 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9600 is_single_device_type_equal(&in->device_list,
9601 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009602 if (config->sample_rate == 0)
9603 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9604 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9605 config->sample_rate != 8000) {
9606 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9607 ret = -EINVAL;
9608 goto err_open;
9609 }
9610 if (config->format == AUDIO_FORMAT_DEFAULT)
9611 config->format = AUDIO_FORMAT_PCM_16_BIT;
9612 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9613 config->format = AUDIO_FORMAT_PCM_16_BIT;
9614 ret = -EINVAL;
9615 goto err_open;
9616 }
9617
9618 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009619 if (adev->ha_proxy_enable &&
9620 is_single_device_type_equal(&in->device_list,
9621 AUDIO_DEVICE_IN_TELEPHONY_RX))
9622 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009623 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009624 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009625 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309626 } else if (in->realtime) {
9627 in->config = pcm_config_audio_capture_rt;
9628 in->config.format = pcm_format_from_audio_format(config->format);
9629 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009630 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9631 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9632 (config->sample_rate == 8000 ||
9633 config->sample_rate == 16000 ||
9634 config->sample_rate == 32000 ||
9635 config->sample_rate == 48000) &&
9636 channel_count == 1) {
9637 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9638 in->config = pcm_config_audio_capture;
9639 frame_size = audio_stream_in_frame_size(&in->stream);
9640 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9641 config->sample_rate,
9642 config->format,
9643 channel_count, false /*is_low_latency*/);
9644 in->config.period_size = buffer_size / frame_size;
9645 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9646 in->config.rate = config->sample_rate;
9647 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009648 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309649 int ret_val;
9650 pthread_mutex_lock(&adev->lock);
9651 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9652 in, config, &channel_mask_updated);
9653 pthread_mutex_unlock(&adev->lock);
9654
9655 if (!ret_val) {
9656 if (channel_mask_updated == true) {
9657 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9658 __func__, config->channel_mask);
9659 ret = -EINVAL;
9660 goto err_open;
9661 }
9662 ALOGD("%s: created multi-channel session succesfully",__func__);
9663 } else if (audio_extn_compr_cap_enabled() &&
9664 audio_extn_compr_cap_format_supported(config->format) &&
9665 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9666 audio_extn_compr_cap_init(in);
9667 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309668 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309669 if (ret)
9670 goto err_open;
9671 } else {
9672 in->config = pcm_config_audio_capture;
9673 in->config.rate = config->sample_rate;
9674 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309675 in->format = config->format;
9676 frame_size = audio_stream_in_frame_size(&in->stream);
9677 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009678 config->format,
9679 channel_count,
9680 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009681 /* prevent division-by-zero */
9682 if (frame_size == 0) {
9683 ALOGE("%s: Error frame_size==0", __func__);
9684 ret = -EINVAL;
9685 goto err_open;
9686 }
9687
Revathi Uddarajud2634032017-12-07 14:42:34 +05309688 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009689 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009690
Revathi Uddarajud2634032017-12-07 14:42:34 +05309691 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9692 /* optionally use VOIP usecase depending on config(s) */
9693 ret = adev_update_voice_comm_input_stream(in, config);
9694 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009695
Revathi Uddarajud2634032017-12-07 14:42:34 +05309696 if (ret) {
9697 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9698 goto err_open;
9699 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009700 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309701
9702 /* assign concurrent capture usecase if record has to caried out from
9703 * actual hardware input source */
9704 if (audio_extn_is_concurrent_capture_enabled() &&
9705 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309706 /* Acquire lock to avoid two concurrent use cases initialized to
9707 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009708
Samyak Jainc37062f2019-04-25 18:41:06 +05309709 if (in->usecase == USECASE_AUDIO_RECORD) {
9710 pthread_mutex_lock(&adev->lock);
9711 if (!(adev->pcm_record_uc_state)) {
9712 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9713 adev->pcm_record_uc_state = 1;
9714 pthread_mutex_unlock(&adev->lock);
9715 } else {
9716 pthread_mutex_unlock(&adev->lock);
9717 /* Assign compress record use case for second record */
9718 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9719 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9720 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9721 if (audio_extn_cin_applicable_stream(in)) {
9722 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309723 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309724 if (ret)
9725 goto err_open;
9726 }
9727 }
9728 }
kunleiz28c73e72019-03-27 17:24:04 +08009729 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009730 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9731 ret = audio_extn_auto_hal_open_input_stream(in);
9732 if (ret) {
9733 ALOGE("%s: Failed to open input stream for bus device", __func__);
9734 ret = -EINVAL;
9735 goto err_open;
9736 }
9737 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009738 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309739 if (audio_extn_ssr_get_stream() != in)
9740 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009741
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009742 in->sample_rate = in->config.rate;
9743
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309744 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9745 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009746 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009747 in->sample_rate, in->bit_width,
9748 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309749 register_format(in->format, in->supported_formats);
9750 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9751 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309752
Aalique Grahame22e49102018-12-18 14:23:57 -08009753 in->error_log = error_log_create(
9754 ERROR_LOG_ENTRIES,
9755 1000000000 /* aggregate consecutive identical errors within one second */);
9756
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009757 /* This stream could be for sound trigger lab,
9758 get sound trigger pcm if present */
9759 audio_extn_sound_trigger_check_and_get_session(in);
9760
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309761 lock_input_stream(in);
9762 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9763 pthread_mutex_lock(&adev->lock);
9764 in->card_status = adev->card_status;
9765 pthread_mutex_unlock(&adev->lock);
9766 pthread_mutex_unlock(&in->lock);
9767
Aalique Grahame22e49102018-12-18 14:23:57 -08009768 stream_app_type_cfg_init(&in->app_type_cfg);
9769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009770 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009771
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009772 ret = io_streams_map_insert(adev, &in->stream.common,
9773 handle, AUDIO_PATCH_HANDLE_NONE);
9774 if (ret != 0)
9775 goto err_open;
9776
Derek Chenf939fb72018-11-13 13:34:41 -08009777 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9778 calloc(1, sizeof(streams_input_ctxt_t));
9779 if (in_ctxt == NULL) {
9780 ALOGE("%s fail to allocate input ctxt", __func__);
9781 ret = -ENOMEM;
9782 goto err_open;
9783 }
9784 in_ctxt->input = in;
9785
9786 pthread_mutex_lock(&adev->lock);
9787 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9788 pthread_mutex_unlock(&adev->lock);
9789
Eric Laurent994a6932013-07-17 11:51:42 -07009790 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009792
9793err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309794 if (in->usecase == USECASE_AUDIO_RECORD) {
9795 pthread_mutex_lock(&adev->lock);
9796 adev->pcm_record_uc_state = 0;
9797 pthread_mutex_unlock(&adev->lock);
9798 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009799 free(in);
9800 *stream_in = NULL;
9801 return ret;
9802}
9803
9804static void adev_close_input_stream(struct audio_hw_device *dev,
9805 struct audio_stream_in *stream)
9806{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009807 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009808 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009809 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309810
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309811 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009812
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009813 if (in == NULL) {
9814 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9815 return;
9816 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009817 io_streams_map_remove(adev, in->capture_handle);
9818
kunleiz70e57612018-12-28 17:50:23 +08009819 /* must deregister from sndmonitor first to prevent races
9820 * between the callback and close_stream
9821 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309822 audio_extn_snd_mon_unregister_listener(stream);
9823
kunleiz70e57612018-12-28 17:50:23 +08009824 /* Disable echo reference if there are no active input, hfp call
9825 * and sound trigger while closing input stream
9826 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009827 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009828 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009829 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9830 struct listnode out_devices;
9831 list_init(&out_devices);
9832 platform_set_echo_reference(adev, false, &out_devices);
9833 } else
kunleiz70e57612018-12-28 17:50:23 +08009834 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309835
Weiyin Jiang2995f662019-04-17 14:25:12 +08009836 error_log_destroy(in->error_log);
9837 in->error_log = NULL;
9838
Pallavid7c7a272018-01-16 11:22:55 +05309839
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009840 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309841 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009842 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309843 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009844 if (ret != 0)
9845 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9846 __func__, ret);
9847 } else
9848 in_standby(&stream->common);
9849
Weiyin Jiang280ea742020-09-08 20:28:22 +08009850 pthread_mutex_destroy(&in->lock);
9851 pthread_mutex_destroy(&in->pre_lock);
9852
Revathi Uddarajud2634032017-12-07 14:42:34 +05309853 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309854 if (in->usecase == USECASE_AUDIO_RECORD) {
9855 adev->pcm_record_uc_state = 0;
9856 }
9857
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009858 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9859 adev->enable_voicerx = false;
9860 }
9861
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009862 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009863 audio_extn_ssr_deinit();
9864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009865
Garmond Leunge2433c32017-09-28 21:51:22 -07009866 if (audio_extn_ffv_get_stream() == in) {
9867 audio_extn_ffv_stream_deinit();
9868 }
9869
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309870 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009871 audio_extn_compr_cap_format_supported(in->config.format))
9872 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309873
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309874 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309875 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009876
Mingming Yinfd7607b2016-01-22 12:48:44 -08009877 if (in->is_st_session) {
9878 ALOGV("%s: sound trigger pcm stop lab", __func__);
9879 audio_extn_sound_trigger_stop_lab(in);
9880 }
Derek Chenf939fb72018-11-13 13:34:41 -08009881 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9882 if (in_ctxt != NULL) {
9883 list_remove(&in_ctxt->list);
9884 free(in_ctxt);
9885 } else {
9886 ALOGW("%s, input stream already closed", __func__);
9887 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009888 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309889 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009890 return;
9891}
9892
Aalique Grahame22e49102018-12-18 14:23:57 -08009893/* verifies input and output devices and their capabilities.
9894 *
9895 * This verification is required when enabling extended bit-depth or
9896 * sampling rates, as not all qcom products support it.
9897 *
9898 * Suitable for calling only on initialization such as adev_open().
9899 * It fills the audio_device use_case_table[] array.
9900 *
9901 * Has a side-effect that it needs to configure audio routing / devices
9902 * in order to power up the devices and read the device parameters.
9903 * It does not acquire any hw device lock. Should restore the devices
9904 * back to "normal state" upon completion.
9905 */
9906static int adev_verify_devices(struct audio_device *adev)
9907{
9908 /* enumeration is a bit difficult because one really wants to pull
9909 * the use_case, device id, etc from the hidden pcm_device_table[].
9910 * In this case there are the following use cases and device ids.
9911 *
9912 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9913 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9914 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9915 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9916 * [USECASE_AUDIO_RECORD] = {0, 0},
9917 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9918 * [USECASE_VOICE_CALL] = {2, 2},
9919 *
9920 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9921 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9922 */
9923
9924 /* should be the usecases enabled in adev_open_input_stream() */
9925 static const int test_in_usecases[] = {
9926 USECASE_AUDIO_RECORD,
9927 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9928 };
9929 /* should be the usecases enabled in adev_open_output_stream()*/
9930 static const int test_out_usecases[] = {
9931 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9932 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9933 };
9934 static const usecase_type_t usecase_type_by_dir[] = {
9935 PCM_PLAYBACK,
9936 PCM_CAPTURE,
9937 };
9938 static const unsigned flags_by_dir[] = {
9939 PCM_OUT,
9940 PCM_IN,
9941 };
9942
9943 size_t i;
9944 unsigned dir;
9945 const unsigned card_id = adev->snd_card;
9946
9947 for (dir = 0; dir < 2; ++dir) {
9948 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9949 const unsigned flags_dir = flags_by_dir[dir];
9950 const size_t testsize =
9951 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9952 const int *testcases =
9953 dir ? test_in_usecases : test_out_usecases;
9954 const audio_devices_t audio_device =
9955 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9956
9957 for (i = 0; i < testsize; ++i) {
9958 const audio_usecase_t audio_usecase = testcases[i];
9959 int device_id;
9960 struct pcm_params **pparams;
9961 struct stream_out out;
9962 struct stream_in in;
9963 struct audio_usecase uc_info;
9964 int retval;
9965
9966 pparams = &adev->use_case_table[audio_usecase];
9967 pcm_params_free(*pparams); /* can accept null input */
9968 *pparams = NULL;
9969
9970 /* find the device ID for the use case (signed, for error) */
9971 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9972 if (device_id < 0)
9973 continue;
9974
9975 /* prepare structures for device probing */
9976 memset(&uc_info, 0, sizeof(uc_info));
9977 uc_info.id = audio_usecase;
9978 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009979 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009980 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009981 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009982 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009983 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009984 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9985 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009986 }
9987 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009988 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009989 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009990 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009991 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009992 uc_info.in_snd_device = SND_DEVICE_NONE;
9993 uc_info.out_snd_device = SND_DEVICE_NONE;
9994 list_add_tail(&adev->usecase_list, &uc_info.list);
9995
9996 /* select device - similar to start_(in/out)put_stream() */
9997 retval = select_devices(adev, audio_usecase);
9998 if (retval >= 0) {
9999 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10000#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010001 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010002 if (*pparams) {
10003 ALOGV("%s: (%s) card %d device %d", __func__,
10004 dir ? "input" : "output", card_id, device_id);
10005 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10006 } else {
10007 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10008 }
10009#endif
10010 }
10011
10012 /* deselect device - similar to stop_(in/out)put_stream() */
10013 /* 1. Get and set stream specific mixer controls */
10014 retval = disable_audio_route(adev, &uc_info);
10015 /* 2. Disable the rx device */
10016 retval = disable_snd_device(adev,
10017 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10018 list_remove(&uc_info.list);
10019 }
10020 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010021 return 0;
10022}
10023
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024int update_patch(unsigned int num_sources,
10025 const struct audio_port_config *sources,
10026 unsigned int num_sinks,
10027 const struct audio_port_config *sinks,
10028 audio_patch_handle_t handle,
10029 struct audio_patch_info *p_info,
10030 patch_type_t patch_type, bool new_patch)
10031{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010032 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010033
10034 if (p_info == NULL) {
10035 ALOGE("%s: Invalid patch pointer", __func__);
10036 return -EINVAL;
10037 }
10038
10039 if (new_patch) {
10040 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10041 if (p_info->patch == NULL) {
10042 ALOGE("%s: Could not allocate patch", __func__);
10043 return -ENOMEM;
10044 }
10045 }
10046
10047 p_info->patch->id = handle;
10048 p_info->patch->num_sources = num_sources;
10049 p_info->patch->num_sinks = num_sinks;
10050
10051 for (int i = 0; i < num_sources; i++)
10052 p_info->patch->sources[i] = sources[i];
10053 for (int i = 0; i < num_sinks; i++)
10054 p_info->patch->sinks[i] = sinks[i];
10055
10056 p_info->patch_type = patch_type;
10057 return 0;
10058}
10059
10060audio_patch_handle_t generate_patch_handle()
10061{
10062 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10063 if (++patch_handle < 0)
10064 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10065 return patch_handle;
10066}
10067
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010068int adev_create_audio_patch(struct audio_hw_device *dev,
10069 unsigned int num_sources,
10070 const struct audio_port_config *sources,
10071 unsigned int num_sinks,
10072 const struct audio_port_config *sinks,
10073 audio_patch_handle_t *handle)
10074{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 int ret = 0;
10076 struct audio_device *adev = (struct audio_device *)dev;
10077 struct audio_patch_info *p_info = NULL;
10078 patch_type_t patch_type = PATCH_NONE;
10079 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10080 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10081 struct audio_stream_info *s_info = NULL;
10082 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010083 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010084 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10085 bool new_patch = false;
10086 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010087
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010088 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10089 num_sources, num_sinks, *handle);
10090
10091 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10092 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10093 ALOGE("%s: Invalid patch arguments", __func__);
10094 ret = -EINVAL;
10095 goto done;
10096 }
10097
10098 if (num_sources > 1) {
10099 ALOGE("%s: Multiple sources are not supported", __func__);
10100 ret = -EINVAL;
10101 goto done;
10102 }
10103
10104 if (sources == NULL || sinks == NULL) {
10105 ALOGE("%s: Invalid sources or sinks port config", __func__);
10106 ret = -EINVAL;
10107 goto done;
10108 }
10109
10110 ALOGV("%s: source role %d, source type %d", __func__,
10111 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010112 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010113
10114 // Populate source/sink information and fetch stream info
10115 switch (sources[0].type) {
10116 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10117 device_type = sources[0].ext.device.type;
10118 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010119 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010120 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10121 patch_type = PATCH_CAPTURE;
10122 io_handle = sinks[0].ext.mix.handle;
10123 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010124 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010125 __func__, device_type, io_handle);
10126 } else {
10127 // Device to device patch is not implemented.
10128 // This space will need changes if audio HAL
10129 // handles device to device patches in the future.
10130 patch_type = PATCH_DEVICE_LOOPBACK;
10131 }
10132 break;
10133 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10134 io_handle = sources[0].ext.mix.handle;
10135 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010136 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010138 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010139 }
10140 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010141 ALOGD("%s: Playback patch from mix handle %d to device %x",
10142 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010143 break;
10144 case AUDIO_PORT_TYPE_SESSION:
10145 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010146 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10147 ret = -EINVAL;
10148 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149 }
10150
10151 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 // Generate patch info and update patch
10154 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010155 *handle = generate_patch_handle();
10156 p_info = (struct audio_patch_info *)
10157 calloc(1, sizeof(struct audio_patch_info));
10158 if (p_info == NULL) {
10159 ALOGE("%s: Failed to allocate memory", __func__);
10160 pthread_mutex_unlock(&adev->lock);
10161 ret = -ENOMEM;
10162 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010163 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010164 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010166 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010167 if (p_info == NULL) {
10168 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10169 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010170 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010171 ret = -EINVAL;
10172 goto done;
10173 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010174 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010176 *handle, p_info, patch_type, new_patch);
10177
10178 // Fetch stream info of associated mix for playback or capture patches
10179 if (p_info->patch_type == PATCH_PLAYBACK ||
10180 p_info->patch_type == PATCH_CAPTURE) {
10181 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10182 if (s_info == NULL) {
10183 ALOGE("%s: Failed to obtain stream info", __func__);
10184 if (new_patch)
10185 free(p_info);
10186 pthread_mutex_unlock(&adev->lock);
10187 ret = -EINVAL;
10188 goto done;
10189 }
10190 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10191 s_info->patch_handle = *handle;
10192 stream = s_info->stream;
10193 }
10194 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195
10196 // Update routing for stream
10197 if (stream != NULL) {
10198 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010199 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010200 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010201 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010202 if (ret < 0) {
10203 pthread_mutex_lock(&adev->lock);
10204 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10205 if (new_patch)
10206 free(p_info);
10207 pthread_mutex_unlock(&adev->lock);
10208 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10209 goto done;
10210 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211 }
10212
10213 // Add new patch to patch map
10214 if (!ret && new_patch) {
10215 pthread_mutex_lock(&adev->lock);
10216 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010217 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010218 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 }
10220
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010221done:
10222 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010223 num_sources,
10224 sources,
10225 num_sinks,
10226 sinks,
10227 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010228 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010229 num_sources,
10230 sources,
10231 num_sinks,
10232 sinks,
10233 handle);
10234 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010235}
10236
10237int adev_release_audio_patch(struct audio_hw_device *dev,
10238 audio_patch_handle_t handle)
10239{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010240 struct audio_device *adev = (struct audio_device *) dev;
10241 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010242 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010243 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010244
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010245 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10246 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10247 ret = -EINVAL;
10248 goto done;
10249 }
10250
10251 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010252 pthread_mutex_lock(&adev->lock);
10253 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010254 if (p_info == NULL) {
10255 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010256 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010257 ret = -EINVAL;
10258 goto done;
10259 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010260 struct audio_patch *patch = p_info->patch;
10261 if (patch == NULL) {
10262 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010263 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010264 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010265 goto done;
10266 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010267 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10268 switch (patch->sources[0].type) {
10269 case AUDIO_PORT_TYPE_MIX:
10270 io_handle = patch->sources[0].ext.mix.handle;
10271 break;
10272 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010273 if (p_info->patch_type == PATCH_CAPTURE)
10274 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010275 break;
10276 case AUDIO_PORT_TYPE_SESSION:
10277 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010278 pthread_mutex_unlock(&adev->lock);
10279 ret = -EINVAL;
10280 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010281 }
10282
10283 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010284 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010285 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010286 if (patch_type == PATCH_PLAYBACK ||
10287 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010288 struct audio_stream_info *s_info =
10289 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10290 if (s_info == NULL) {
10291 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10292 pthread_mutex_unlock(&adev->lock);
10293 goto done;
10294 }
10295 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10296 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010297 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010298 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010299
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010300 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010301 struct listnode devices;
10302 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010303 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010304 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010305 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010306 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010307 }
10308
10309 if (ret < 0)
10310 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10311
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010312done:
10313 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10314 audio_extn_auto_hal_release_audio_patch(dev, handle);
10315
10316 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010317 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010318}
10319
10320int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10321{
Derek Chenf13dd492018-11-13 14:53:51 -080010322 int ret = 0;
10323
10324 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10325 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10326 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010327}
10328
10329int adev_set_audio_port_config(struct audio_hw_device *dev,
10330 const struct audio_port_config *config)
10331{
Derek Chenf13dd492018-11-13 14:53:51 -080010332 int ret = 0;
10333
10334 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10335 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10336 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010337}
10338
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010339static int adev_dump(const audio_hw_device_t *device __unused,
10340 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010341{
10342 return 0;
10343}
10344
10345static int adev_close(hw_device_t *device)
10346{
Aalique Grahame22e49102018-12-18 14:23:57 -080010347 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010348 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010349
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010350 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010351 return 0;
10352
10353 pthread_mutex_lock(&adev_init_lock);
10354
10355 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010356 if (audio_extn_spkr_prot_is_enabled())
10357 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010358 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010359 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010360 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010361 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010362 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010363 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010364 audio_extn_utils_release_streams_cfg_lists(
10365 &adev->streams_output_cfg_list,
10366 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010367 if (audio_extn_qap_is_enabled())
10368 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010369 if (audio_extn_qaf_is_enabled())
10370 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010371 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010372 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010373 free(adev->snd_dev_ref_cnt);
10374 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010375 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10376 pcm_params_free(adev->use_case_table[i]);
10377 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010378 if (adev->adm_deinit)
10379 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010380 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010381 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010382 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010383 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010384 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010385 if (adev->device_cfg_params) {
10386 free(adev->device_cfg_params);
10387 adev->device_cfg_params = NULL;
10388 }
Derek Chend2530072014-11-24 12:39:14 -080010389 if(adev->ext_hw_plugin)
10390 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010391 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010392 free_map(adev->patch_map);
10393 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010394 free(device);
10395 adev = NULL;
10396 }
10397 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010398 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010399 return 0;
10400}
10401
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010402/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10403 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10404 * just that it _might_ work.
10405 */
10406static int period_size_is_plausible_for_low_latency(int period_size)
10407{
10408 switch (period_size) {
10409 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010410 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010411 case 240:
10412 case 320:
10413 case 480:
10414 return 1;
10415 default:
10416 return 0;
10417 }
10418}
10419
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010420static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10421{
10422 bool is_snd_card_status = false;
10423 bool is_ext_device_status = false;
10424 char value[32];
10425 int card = -1;
10426 card_status_t status;
10427
10428 if (cookie != adev || !parms)
10429 return;
10430
10431 if (!parse_snd_card_status(parms, &card, &status)) {
10432 is_snd_card_status = true;
10433 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10434 is_ext_device_status = true;
10435 } else {
10436 // not a valid event
10437 return;
10438 }
10439
10440 pthread_mutex_lock(&adev->lock);
10441 if (card == adev->snd_card || is_ext_device_status) {
10442 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010443 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010444 adev->card_status = status;
10445 platform_snd_card_update(adev->platform, status);
10446 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010447 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010448 if (status == CARD_STATUS_OFFLINE)
10449 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010450 } else if (is_ext_device_status) {
10451 platform_set_parameters(adev->platform, parms);
10452 }
10453 }
10454 pthread_mutex_unlock(&adev->lock);
10455 return;
10456}
10457
Weiyin Jiang280ea742020-09-08 20:28:22 +080010458/* adev lock held */
10459int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010460{
10461 struct audio_usecase *uc_info;
10462 float left_p;
10463 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010464 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010465
10466 uc_info = get_usecase_from_list(adev, out->usecase);
10467 if (uc_info == NULL) {
10468 ALOGE("%s: Could not find the usecase (%d) in the list",
10469 __func__, out->usecase);
10470 return -EINVAL;
10471 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010472 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010473
10474 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10475 out->usecase, use_case_table[out->usecase]);
10476
10477 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010478 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010479 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010480 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010482 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10483 select_devices(adev, uc_info->id);
Zhou Songd01e7a22020-09-23 22:49:01 +080010484 if (is_offload_usecase(out->usecase) &&
Weiyin Jiang280ea742020-09-08 20:28:22 +080010485 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10486 if (out->a2dp_compress_mute) {
10487 out->a2dp_compress_mute = false;
10488 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10489 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010490 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010491 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010492 out->muted = false;
10493 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010494 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010495 pthread_mutex_lock(&out->latch_lock);
Zhou Songd01e7a22020-09-23 22:49:01 +080010496 if (is_offload_usecase(out->usecase)) {
Zhou Songc576a452019-09-09 14:17:40 +080010497 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010498 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010499 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010500 assign_devices(&devices, &out->device_list);
10501 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010502 left_p = out->volume_l;
10503 right_p = out->volume_r;
10504 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10505 compress_pause(out->compr);
10506 out_set_compr_volume(&out->stream, (float)0, (float)0);
10507 out->a2dp_compress_mute = true;
10508 select_devices(adev, out->usecase);
10509 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10510 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010511 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010512 out->volume_l = left_p;
10513 out->volume_r = right_p;
10514 }
Zhou Songc576a452019-09-09 14:17:40 +080010515 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010516 // mute for non offloaded streams
10517 if (audio_extn_a2dp_source_is_suspended()) {
10518 out->muted = true;
10519 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010520 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010521 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010522 }
10523 ALOGV("%s: exit", __func__);
10524 return 0;
10525}
10526
Haynes Mathew George01156f92018-04-13 15:29:54 -070010527void adev_on_battery_status_changed(bool charging)
10528{
10529 pthread_mutex_lock(&adev->lock);
10530 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10531 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010532 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010533 pthread_mutex_unlock(&adev->lock);
10534}
10535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010536static int adev_open(const hw_module_t *module, const char *name,
10537 hw_device_t **device)
10538{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010539 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010540 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010541 char mixer_ctl_name[128] = {0};
10542 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010543
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010544 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010545 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10546
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010547 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010548 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010549 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010550 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010551 ALOGD("%s: returning existing instance of adev", __func__);
10552 ALOGD("%s: exit", __func__);
10553 pthread_mutex_unlock(&adev_init_lock);
10554 return 0;
10555 }
10556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010557 adev = calloc(1, sizeof(struct audio_device));
10558
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010559 if (!adev) {
10560 pthread_mutex_unlock(&adev_init_lock);
10561 return -ENOMEM;
10562 }
10563
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010564 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10565
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010566 // register audio ext hidl at the earliest
10567 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010568#ifdef DYNAMIC_LOG_ENABLED
10569 register_for_dynamic_logging("hal");
10570#endif
10571
Derek Chenf939fb72018-11-13 13:34:41 -080010572 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010573 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010574 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10575 maj_version = atoi(value);
10576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010577 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010578 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010579 adev->device.common.module = (struct hw_module_t *)module;
10580 adev->device.common.close = adev_close;
10581
10582 adev->device.init_check = adev_init_check;
10583 adev->device.set_voice_volume = adev_set_voice_volume;
10584 adev->device.set_master_volume = adev_set_master_volume;
10585 adev->device.get_master_volume = adev_get_master_volume;
10586 adev->device.set_master_mute = adev_set_master_mute;
10587 adev->device.get_master_mute = adev_get_master_mute;
10588 adev->device.set_mode = adev_set_mode;
10589 adev->device.set_mic_mute = adev_set_mic_mute;
10590 adev->device.get_mic_mute = adev_get_mic_mute;
10591 adev->device.set_parameters = adev_set_parameters;
10592 adev->device.get_parameters = adev_get_parameters;
10593 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10594 adev->device.open_output_stream = adev_open_output_stream;
10595 adev->device.close_output_stream = adev_close_output_stream;
10596 adev->device.open_input_stream = adev_open_input_stream;
10597 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010598 adev->device.create_audio_patch = adev_create_audio_patch;
10599 adev->device.release_audio_patch = adev_release_audio_patch;
10600 adev->device.get_audio_port = adev_get_audio_port;
10601 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010602 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010603 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010604
10605 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010606 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010607 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010608 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010609 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010610 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010611 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010612 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010613 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010614 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010615 /* Init audio and voice feature */
10616 audio_extn_feature_init();
10617 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010618 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010619 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010620 list_init(&adev->active_inputs_list);
10621 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010622 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010623 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10624 audio_extn_utils_hash_eq);
10625 if (!adev->io_streams_map) {
10626 ALOGE("%s: Could not create io streams map", __func__);
10627 ret = -ENOMEM;
10628 goto adev_open_err;
10629 }
10630 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10631 audio_extn_utils_hash_eq);
10632 if (!adev->patch_map) {
10633 ALOGE("%s: Could not create audio patch map", __func__);
10634 ret = -ENOMEM;
10635 goto adev_open_err;
10636 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010637 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010638 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010639 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010640 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010641 adev->perf_lock_opts[0] = 0x101;
10642 adev->perf_lock_opts[1] = 0x20E;
10643 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010644 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010645 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010646 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010647 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010648 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010649
Zhou Song68ebc352019-12-05 17:11:15 +080010650 audio_extn_perf_lock_init();
10651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010652 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010653 adev->platform = platform_init(adev);
10654 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010655 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010656 ret = -EINVAL;
10657 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010658 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010659
Aalique Grahame22e49102018-12-18 14:23:57 -080010660 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010661 if (audio_extn_qap_is_enabled()) {
10662 ret = audio_extn_qap_init(adev);
10663 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010664 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010665 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010666 }
10667 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10668 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10669 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010670
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010671 if (audio_extn_qaf_is_enabled()) {
10672 ret = audio_extn_qaf_init(adev);
10673 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010674 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010675 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010676 }
10677
10678 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10679 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10680 }
10681
Derek Chenae7b0342019-02-08 15:17:04 -080010682 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010683 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10684
Eric Laurentc4aef752013-09-12 17:45:53 -070010685 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10686 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10687 if (adev->visualizer_lib == NULL) {
10688 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10689 } else {
10690 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10691 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010692 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010693 "visualizer_hal_start_output");
10694 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010695 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010696 "visualizer_hal_stop_output");
10697 }
10698 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010699 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010700 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010701 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010702 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010703 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010704 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010705
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010706 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10707 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10708 if (adev->offload_effects_lib == NULL) {
10709 ALOGE("%s: DLOPEN failed for %s", __func__,
10710 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10711 } else {
10712 ALOGV("%s: DLOPEN successful for %s", __func__,
10713 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10714 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010715 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010716 "offload_effects_bundle_hal_start_output");
10717 adev->offload_effects_stop_output =
10718 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10719 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010720 adev->offload_effects_set_hpx_state =
10721 (int (*)(bool))dlsym(adev->offload_effects_lib,
10722 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010723 adev->offload_effects_get_parameters =
10724 (void (*)(struct str_parms *, struct str_parms *))
10725 dlsym(adev->offload_effects_lib,
10726 "offload_effects_bundle_get_parameters");
10727 adev->offload_effects_set_parameters =
10728 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10729 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010730 }
10731 }
10732
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010733 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10734 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10735 if (adev->adm_lib == NULL) {
10736 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10737 } else {
10738 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10739 adev->adm_init = (adm_init_t)
10740 dlsym(adev->adm_lib, "adm_init");
10741 adev->adm_deinit = (adm_deinit_t)
10742 dlsym(adev->adm_lib, "adm_deinit");
10743 adev->adm_register_input_stream = (adm_register_input_stream_t)
10744 dlsym(adev->adm_lib, "adm_register_input_stream");
10745 adev->adm_register_output_stream = (adm_register_output_stream_t)
10746 dlsym(adev->adm_lib, "adm_register_output_stream");
10747 adev->adm_deregister_stream = (adm_deregister_stream_t)
10748 dlsym(adev->adm_lib, "adm_deregister_stream");
10749 adev->adm_request_focus = (adm_request_focus_t)
10750 dlsym(adev->adm_lib, "adm_request_focus");
10751 adev->adm_abandon_focus = (adm_abandon_focus_t)
10752 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010753 adev->adm_set_config = (adm_set_config_t)
10754 dlsym(adev->adm_lib, "adm_set_config");
10755 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10756 dlsym(adev->adm_lib, "adm_request_focus_v2");
10757 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10758 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10759 adev->adm_on_routing_change = (adm_on_routing_change_t)
10760 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010761 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10762 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010763 }
10764 }
10765
Aalique Grahame22e49102018-12-18 14:23:57 -080010766 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010767 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010768 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010769 //initialize this to false for now,
10770 //this will be set to true through set param
10771 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010772
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010773 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010774 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010775
10776 if (k_enable_extended_precision)
10777 adev_verify_devices(adev);
10778
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010779 adev->dsp_bit_width_enforce_mode =
10780 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010781
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010782 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10783 &adev->streams_output_cfg_list,
10784 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010785
Kiran Kandi910e1862013-10-29 13:29:42 -070010786 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010787
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010788 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010789 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010790 trial = atoi(value);
10791 if (period_size_is_plausible_for_low_latency(trial)) {
10792 pcm_config_low_latency.period_size = trial;
10793 pcm_config_low_latency.start_threshold = trial / 4;
10794 pcm_config_low_latency.avail_min = trial / 4;
10795 configured_low_latency_capture_period_size = trial;
10796 }
10797 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010798 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10799 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010800 trial = atoi(value);
10801 if (period_size_is_plausible_for_low_latency(trial)) {
10802 configured_low_latency_capture_period_size = trial;
10803 }
10804 }
10805
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010806 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10807
Eric Laurent4b084132018-10-19 17:33:43 -070010808 adev->camera_orientation = CAMERA_DEFAULT;
10809
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010810 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010811 af_period_multiplier = atoi(value);
10812 if (af_period_multiplier < 0)
10813 af_period_multiplier = 2;
10814 else if (af_period_multiplier > 4)
10815 af_period_multiplier = 4;
10816
10817 ALOGV("new period_multiplier = %d", af_period_multiplier);
10818 }
10819
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010820 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010821
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010822 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010823 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010824 pthread_mutex_unlock(&adev_init_lock);
10825
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010826 if (adev->adm_init)
10827 adev->adm_data = adev->adm_init();
10828
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010829 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010830 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010831
10832 audio_extn_snd_mon_init();
10833 pthread_mutex_lock(&adev->lock);
10834 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10835 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010836 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10837 /*
10838 * if the battery state callback happens before charging can be queried,
10839 * it will be guarded with the adev->lock held in the cb function and so
10840 * the callback value will reflect the latest state
10841 */
10842 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010843 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010844 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010845 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010846 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010847 /* Allocate memory for Device config params */
10848 adev->device_cfg_params = (struct audio_device_config_param*)
10849 calloc(platform_get_max_codec_backend(),
10850 sizeof(struct audio_device_config_param));
10851 if (adev->device_cfg_params == NULL)
10852 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010853
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010854 /*
10855 * Check if new PSPD matrix mixer control is supported. If not
10856 * supported, then set flag so that old mixer ctrl is sent while
10857 * sending pspd coefficients on older kernel version. Query mixer
10858 * control for default pcm id and channel value one.
10859 */
10860 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10861 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10862
10863 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10864 if (!ctl) {
10865 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10866 __func__, mixer_ctl_name);
10867 adev->use_old_pspd_mix_ctrl = true;
10868 }
10869
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010870 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010871 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010872
10873adev_open_err:
10874 free_map(adev->patch_map);
10875 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010876 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010877 pthread_mutex_destroy(&adev->lock);
10878 free(adev);
10879 adev = NULL;
10880 *device = NULL;
10881 pthread_mutex_unlock(&adev_init_lock);
10882 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010883}
10884
10885static struct hw_module_methods_t hal_module_methods = {
10886 .open = adev_open,
10887};
10888
10889struct audio_module HAL_MODULE_INFO_SYM = {
10890 .common = {
10891 .tag = HARDWARE_MODULE_TAG,
10892 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10893 .hal_api_version = HARDWARE_HAL_API_VERSION,
10894 .id = AUDIO_HARDWARE_MODULE_ID,
10895 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010896 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010897 .methods = &hal_module_methods,
10898 },
10899};