blob: 8e4f9e1f7008fb4a45a327200909fe70dfe298aa [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);
Manish Dewangan58229382017-02-02 15:48:41 +05301289 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1290 out = usecase->stream.out;
1291 if (out && out->compr)
1292 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1293 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301294
1295 if (usecase->type == PCM_CAPTURE) {
1296 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001297 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301298 ALOGD("%s: set custom mtmx params v1", __func__);
1299 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1300 }
1301 } else {
1302 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1303 }
Manish Dewangan58229382017-02-02 15:48:41 +05301304
Andy Hung756ecc12018-10-19 17:47:12 -07001305 // we shouldn't truncate mixer_path
1306 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1307 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1308 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001309 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001310 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301311 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1312 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1313 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1314 if (parms) {
1315 audio_extn_fm_set_parameters(adev, parms);
1316 str_parms_destroy(parms);
1317 }
1318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001319 ALOGV("%s: exit", __func__);
1320 return 0;
1321}
1322
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001323int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001324 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001325{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001327 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301328 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001329
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301330 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001331 return -EINVAL;
1332
1333 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301334 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001335 snd_device = usecase->in_snd_device;
1336 else
1337 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001338
1339 /* disable island and power mode on supported device for voice call */
1340 if (usecase->type == VOICE_CALL) {
1341 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1342 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1343 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1344 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1345 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1346 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001347 if (voice_is_lte_call_active(adev))
1348 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001349 ALOGD("%s: disable island cfg and power mode in voice tx path",
1350 __func__);
1351 }
1352 }
1353 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1354 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1355 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1356 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1357 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1358 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1359 ALOGD("%s: disable island cfg and power mode in voice rx path",
1360 __func__);
1361 }
1362 }
1363 }
1364
Andy Hung756ecc12018-10-19 17:47:12 -07001365 // we shouldn't truncate mixer_path
1366 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1367 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1368 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001369 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001370 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001371 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001372 if (usecase->type == PCM_CAPTURE) {
1373 struct stream_in *in = usecase->stream.in;
1374 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001375 struct listnode out_devices;
1376 list_init(&out_devices);
1377 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001378 in->ec_opened = false;
1379 }
1380 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001381 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301382 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301383
1384 if (usecase->type == PCM_CAPTURE) {
1385 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001386 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301387 ALOGD("%s: reset custom mtmx params v1", __func__);
1388 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1389 }
1390 } else {
1391 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1392 }
1393
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001394 if ((usecase->type == PCM_PLAYBACK) &&
1395 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301396 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001398 ALOGV("%s: exit", __func__);
1399 return 0;
1400}
1401
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001402int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001403 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301405 int i, num_devices = 0;
1406 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001407 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1408
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001409 if (snd_device < SND_DEVICE_MIN ||
1410 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001411 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001412 return -EINVAL;
1413 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001415 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001416 ALOGE("%s: Invalid sound device returned", __func__);
1417 return -EINVAL;
1418 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001419
1420 adev->snd_dev_ref_cnt[snd_device]++;
1421
1422 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1423 (platform_split_snd_device(adev->platform,
1424 snd_device,
1425 &num_devices,
1426 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001427 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001428 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001429 /* Set backend config for A2DP to ensure slimbus configuration
1430 is correct if A2DP is already active and backend is closed
1431 and re-opened */
1432 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1433 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 return 0;
1435 }
1436
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001437 if (audio_extn_spkr_prot_is_enabled())
1438 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001439
Aalique Grahame22e49102018-12-18 14:23:57 -08001440 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1441
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001442 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1443 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1445 goto err;
1446 }
1447 audio_extn_dev_arbi_acquire(snd_device);
1448 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001449 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001450 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001451 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001452 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001453 } else if (platform_split_snd_device(adev->platform,
1454 snd_device,
1455 &num_devices,
1456 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301457 for (i = 0; i < num_devices; i++) {
1458 enable_snd_device(adev, new_snd_devices[i]);
1459 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001460 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001461 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001462 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301463
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001464 /* enable island and power mode on supported device */
1465 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1466 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1467 platform_set_island_cfg_on_device(adev, snd_device, true);
1468 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001469 if (voice_is_lte_call_active(adev) &&
1470 (snd_device >= SND_DEVICE_IN_BEGIN &&
1471 snd_device < SND_DEVICE_IN_END))
1472 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001473 ALOGD("%s: enable island cfg and power mode on: %s",
1474 __func__, device_name);
1475 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301476
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301477 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1478 if (audio_extn_a2dp_start_playback() < 0) {
1479 ALOGE(" fail to configure A2dp Source control path ");
1480 goto err;
1481 } else {
1482 adev->a2dp_started = true;
1483 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001484 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001485
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001486 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1487 (audio_extn_a2dp_start_capture() < 0)) {
1488 ALOGE(" fail to configure A2dp Sink control path ");
1489 goto err;
1490 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301491
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001492 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1493 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1494 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1495 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1496 ALOGE(" fail to configure sco control path ");
1497 goto err;
1498 }
Zhou Song12c29502019-03-16 10:37:18 +08001499 }
1500
Zhou Song331c8e52019-08-26 14:16:12 +08001501 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001502 /* due to the possibility of calibration overwrite between listen
1503 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001504 audio_extn_sound_trigger_update_device_status(snd_device,
1505 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301506 audio_extn_listen_update_device_status(snd_device,
1507 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001508 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001509 audio_extn_sound_trigger_update_device_status(snd_device,
1510 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301511 audio_extn_listen_update_device_status(snd_device,
1512 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001514 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001515 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001516 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301517
1518 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1519 !adev->native_playback_enabled &&
1520 audio_is_true_native_stream_active(adev)) {
1521 ALOGD("%s: %d: napb: enabling native mode in hardware",
1522 __func__, __LINE__);
1523 audio_route_apply_and_update_path(adev->audio_route,
1524 "true-native-mode");
1525 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301526 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301527 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1528 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001529 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001530 ALOGD("%s: init ec ref loopback", __func__);
1531 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001535err:
1536 adev->snd_dev_ref_cnt[snd_device]--;
1537 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538}
1539
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001540int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001541 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001542{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301543 int i, num_devices = 0;
1544 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001545 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1546
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001547 if (snd_device < SND_DEVICE_MIN ||
1548 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001549 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001550 return -EINVAL;
1551 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001552
1553 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1554 ALOGE("%s: Invalid sound device returned", __func__);
1555 return -EINVAL;
1556 }
1557
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1559 ALOGE("%s: device ref cnt is already 0", __func__);
1560 return -EINVAL;
1561 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001564
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001565
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001567 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301568
Aalique Grahame22e49102018-12-18 14:23:57 -08001569 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1570
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001571 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1572 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001573 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001574
1575 // when speaker device is disabled, reset swap.
1576 // will be renabled on usecase start
1577 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001578 } else if (platform_split_snd_device(adev->platform,
1579 snd_device,
1580 &num_devices,
1581 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301582 for (i = 0; i < num_devices; i++) {
1583 disable_snd_device(adev, new_snd_devices[i]);
1584 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001585 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001586 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001587 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001588 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001589
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301590 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301591 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301592 adev->a2dp_started = false;
1593 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001594 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001595 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001596 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301597 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001598 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301599 adev->native_playback_enabled) {
1600 ALOGD("%s: %d: napb: disabling native mode in hardware",
1601 __func__, __LINE__);
1602 audio_route_reset_and_update_path(adev->audio_route,
1603 "true-native-mode");
1604 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001605 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301606 adev->asrc_mode_enabled) {
1607 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301608 disable_asrc_mode(adev);
1609 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001610 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301611 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001612 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001613 ALOGD("%s: deinit ec ref loopback", __func__);
1614 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1615 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001616
1617 audio_extn_utils_release_snd_device(snd_device);
1618 } else {
1619 if (platform_split_snd_device(adev->platform,
1620 snd_device,
1621 &num_devices,
1622 new_snd_devices) == 0) {
1623 for (i = 0; i < num_devices; i++) {
1624 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1625 }
1626 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001627 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 return 0;
1630}
1631
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001632/*
1633 legend:
1634 uc - existing usecase
1635 new_uc - new usecase
1636 d1, d11, d2 - SND_DEVICE enums
1637 a1, a2 - corresponding ANDROID device enums
1638 B1, B2 - backend strings
1639
1640case 1
1641 uc->dev d1 (a1) B1
1642 new_uc->dev d1 (a1), d2 (a2) B1, B2
1643
1644 resolution: disable and enable uc->dev on d1
1645
1646case 2
1647 uc->dev d1 (a1) B1
1648 new_uc->dev d11 (a1) B1
1649
1650 resolution: need to switch uc since d1 and d11 are related
1651 (e.g. speaker and voice-speaker)
1652 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1653
1654case 3
1655 uc->dev d1 (a1) B1
1656 new_uc->dev d2 (a2) B2
1657
1658 resolution: no need to switch uc
1659
1660case 4
1661 uc->dev d1 (a1) B1
1662 new_uc->dev d2 (a2) B1
1663
1664 resolution: disable enable uc-dev on d2 since backends match
1665 we cannot enable two streams on two different devices if they
1666 share the same backend. e.g. if offload is on speaker device using
1667 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1668 using the same backend, offload must also be switched to voice-handset.
1669
1670case 5
1671 uc->dev d1 (a1) B1
1672 new_uc->dev d1 (a1), d2 (a2) B1
1673
1674 resolution: disable enable uc-dev on d2 since backends match
1675 we cannot enable two streams on two different devices if they
1676 share the same backend.
1677
1678case 6
1679 uc->dev d1 (a1) B1
1680 new_uc->dev d2 (a1) B2
1681
1682 resolution: no need to switch
1683
1684case 7
1685 uc->dev d1 (a1), d2 (a2) B1, B2
1686 new_uc->dev d1 (a1) B1
1687
1688 resolution: no need to switch
1689
Zhou Song4ba65882018-07-09 14:48:07 +08001690case 8
1691 uc->dev d1 (a1) B1
1692 new_uc->dev d11 (a1), d2 (a2) B1, B2
1693 resolution: compared to case 1, for this case, d1 and d11 are related
1694 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301695
1696case 9
1697 uc->dev d1 (a1), d2(a2) B1 B2
1698 new_uc->dev d1 (a1), d22 (a2) B1, B2
1699 resolution: disable enable uc-dev on d2 since backends match
1700 we cannot enable two streams on two different devices if they
1701 share the same backend. This is special case for combo use case
1702 with a2dp and sco devices which uses same backend.
1703 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001704*/
1705static snd_device_t derive_playback_snd_device(void * platform,
1706 struct audio_usecase *uc,
1707 struct audio_usecase *new_uc,
1708 snd_device_t new_snd_device)
1709{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001710 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001711
1712 snd_device_t d1 = uc->out_snd_device;
1713 snd_device_t d2 = new_snd_device;
1714
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001715 list_init(&a1);
1716 list_init(&a2);
1717
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301718 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301719 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001720 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1721 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301722 break;
1723 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001724 assign_devices(&a1, &uc->stream.out->device_list);
1725 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301726 break;
1727 }
1728
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001729 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001730 if (!compare_devices(&a1, &a2) &&
1731 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001732 snd_device_t d3[2];
1733 int num_devices = 0;
1734 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001735 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001736 &num_devices,
1737 d3);
1738 if (ret < 0) {
1739 if (ret != -ENOSYS) {
1740 ALOGW("%s failed to split snd_device %d",
1741 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001742 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001743 }
1744 goto end;
1745 }
1746
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001747 if (platform_check_backends_match(d3[0], d3[1])) {
1748 return d2; // case 5
1749 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301750 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1751 platform_check_backends_match(d1, d2))
1752 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001753 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301754 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001755 // check if d1 is related to any of d3's
1756 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001757 return d1; // case 1
1758 else
1759 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001760 }
1761 } else {
1762 if (platform_check_backends_match(d1, d2)) {
1763 return d2; // case 2, 4
1764 } else {
1765 return d1; // case 6, 3
1766 }
1767 }
1768
1769end:
1770 return d2; // return whatever was calculated before.
1771}
1772
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301774 struct audio_usecase *uc_info,
1775 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001776{
1777 struct listnode *node;
1778 struct audio_usecase *usecase;
1779 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301780 snd_device_t uc_derive_snd_device;
1781 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001782 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1783 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001784 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301785 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001786 /*
1787 * This function is to make sure that all the usecases that are active on
1788 * the hardware codec backend are always routed to any one device that is
1789 * handled by the hardware codec.
1790 * For example, if low-latency and deep-buffer usecases are currently active
1791 * on speaker and out_set_parameters(headset) is received on low-latency
1792 * output, then we have to make sure deep-buffer is also switched to headset,
1793 * because of the limitation that both the devices cannot be enabled
1794 * at the same time as they share the same backend.
1795 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001796 /*
1797 * This call is to check if we need to force routing for a particular stream
1798 * If there is a backend configuration change for the device when a
1799 * new stream starts, then ADM needs to be closed and re-opened with the new
1800 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001801 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001802 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001803 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1804 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301805 /* For a2dp device reconfigure all active sessions
1806 * with new AFE encoder format based on a2dp state
1807 */
1808 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301809 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1810 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301811 audio_extn_a2dp_is_force_device_switch()) {
1812 force_routing = true;
1813 force_restart_session = true;
1814 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001815
1816 /*
1817 * Island cfg and power mode config needs to set before AFE port start.
1818 * Set force routing in case of voice device was enable before.
1819 */
1820 if (uc_info->type == VOICE_CALL &&
1821 voice_extn_is_voice_power_mode_supported() &&
1822 platform_check_and_update_island_power_status(adev->platform,
1823 uc_info,
1824 snd_device)) {
1825 force_routing = true;
1826 ALOGD("%s:becf: force routing %d for power mode supported device",
1827 __func__, force_routing);
1828 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301829 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001832 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001833 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1835 switch_device[i] = false;
1836
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001839
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301840 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1841 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301842 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301843 platform_get_snd_device_name(usecase->out_snd_device),
1844 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301845 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1846 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301847 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1848 usecase, uc_info, snd_device);
1849 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001850 (is_codec_backend_out_device_type(&usecase->device_list) ||
1851 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1852 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1853 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1854 is_a2dp_out_device_type(&usecase->device_list) ||
1855 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301856 ((force_restart_session) ||
1857 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301858 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1859 __func__, use_case_table[usecase->id],
1860 platform_get_snd_device_name(usecase->out_snd_device));
1861 disable_audio_route(adev, usecase);
1862 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301863 /* Enable existing usecase on derived playback device */
1864 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301865 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 }
1868 }
1869
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301870 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1871 num_uc_to_switch);
1872
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001874 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301876 /* Make sure the previous devices to be disabled first and then enable the
1877 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 list_for_each(node, &adev->usecase_list) {
1879 usecase = node_to_item(node, struct audio_usecase, list);
1880 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001881 /* Check if output sound device to be switched can be split and if any
1882 of the split devices match with derived sound device */
1883 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1884 &num_devices, split_snd_devices) == 0) {
1885 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1886 for (i = 0; i < num_devices; i++) {
1887 /* Disable devices that do not match with derived sound device */
1888 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1889 disable_snd_device(adev, split_snd_devices[i]);
1890 }
1891 } else {
1892 disable_snd_device(adev, usecase->out_snd_device);
1893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 }
1895 }
1896
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001900 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1901 &num_devices, split_snd_devices) == 0) {
1902 /* Enable derived sound device only if it does not match with
1903 one of the split sound devices. This is because the matching
1904 sound device was not disabled */
1905 bool should_enable = true;
1906 for (i = 0; i < num_devices; i++) {
1907 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1908 should_enable = false;
1909 break;
1910 }
1911 }
1912 if (should_enable)
1913 enable_snd_device(adev, derive_snd_device[usecase->id]);
1914 } else {
1915 enable_snd_device(adev, derive_snd_device[usecase->id]);
1916 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001917 }
1918 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001920 /* Re-route all the usecases on the shared backend other than the
1921 specified usecase to new snd devices */
1922 list_for_each(node, &adev->usecase_list) {
1923 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301924 /* Update the out_snd_device only before enabling the audio route */
1925 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301926 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301927 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301928 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301929 use_case_table[usecase->id],
1930 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001931 /* Update voc calibration before enabling VoIP route */
1932 if (usecase->type == VOIP_CALL)
1933 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001934 usecase->out_snd_device,
1935 platform_get_input_snd_device(
1936 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301937 &uc_info->device_list,
1938 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301939 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301940 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001941 out_set_voip_volume(&usecase->stream.out->stream,
1942 usecase->stream.out->volume_l,
1943 usecase->stream.out->volume_r);
1944 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301945 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001946 }
1947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948 }
1949}
1950
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301951static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001952 struct audio_usecase *uc_info,
1953 snd_device_t snd_device)
1954{
1955 struct listnode *node;
1956 struct audio_usecase *usecase;
1957 bool switch_device[AUDIO_USECASE_MAX];
1958 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001959 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001960 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001961
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301962 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1963 snd_device);
1964 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301965
1966 /*
1967 * Make sure out devices is checked against out codec backend device and
1968 * also in devices against in codec backend. Checking out device against in
1969 * codec backend or vice versa causes issues.
1970 */
1971 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001972 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001973
1974 /*
1975 * Island cfg and power mode config needs to set before AFE port start.
1976 * Set force routing in case of voice device was enable before.
1977 */
1978
1979 if (uc_info->type == VOICE_CALL &&
1980 voice_extn_is_voice_power_mode_supported() &&
1981 platform_check_and_update_island_power_status(adev->platform,
1982 uc_info,
1983 snd_device)) {
1984 force_routing = true;
1985 ALOGD("%s:becf: force routing %d for power mode supported device",
1986 __func__, force_routing);
1987 }
1988
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001989 /*
1990 * This function is to make sure that all the active capture usecases
1991 * are always routed to the same input sound device.
1992 * For example, if audio-record and voice-call usecases are currently
1993 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1994 * is received for voice call then we have to make sure that audio-record
1995 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1996 * because of the limitation that two devices cannot be enabled
1997 * at the same time if they share the same backend.
1998 */
1999 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2000 switch_device[i] = false;
2001
2002 list_for_each(node, &adev->usecase_list) {
2003 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302004 /*
2005 * TODO: Enhance below condition to handle BT sco/USB multi recording
2006 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302007
2008 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2009 (usecase->in_snd_device != snd_device || force_routing));
2010 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2011 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2012 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002013 ((backend_check_cond &&
2014 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002015 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002016 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002017 is_single_device_type_equal(&usecase->device_list,
2018 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002019 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002020 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002021 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302022 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002023 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002024 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002025 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002026 switch_device[usecase->id] = true;
2027 num_uc_to_switch++;
2028 }
2029 }
2030
2031 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002032 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002033
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302034 /* Make sure the previous devices to be disabled first and then enable the
2035 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002036 list_for_each(node, &adev->usecase_list) {
2037 usecase = node_to_item(node, struct audio_usecase, list);
2038 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002039 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002040 }
2041 }
2042
2043 list_for_each(node, &adev->usecase_list) {
2044 usecase = node_to_item(node, struct audio_usecase, list);
2045 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002046 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002047 }
2048 }
2049
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002050 /* Re-route all the usecases on the shared backend other than the
2051 specified usecase to new snd devices */
2052 list_for_each(node, &adev->usecase_list) {
2053 usecase = node_to_item(node, struct audio_usecase, list);
2054 /* Update the in_snd_device only before enabling the audio route */
2055 if (switch_device[usecase->id] ) {
2056 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002057 if (usecase->type != VOICE_CALL) {
2058 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302059 if (usecase->type == VOIP_CALL) {
2060 snd_device_t voip_snd_device;
2061 voip_snd_device = platform_get_output_snd_device(adev->platform,
2062 uc_info->stream.out,
2063 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002064 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302065 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002066 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302067 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302068 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002069 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002070 }
2071 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002072 }
2073}
2074
Mingming Yin3a941d42016-02-17 18:08:05 -08002075static void reset_hdmi_sink_caps(struct stream_out *out) {
2076 int i = 0;
2077
2078 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2079 out->supported_channel_masks[i] = 0;
2080 }
2081 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2082 out->supported_formats[i] = 0;
2083 }
2084 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2085 out->supported_sample_rates[i] = 0;
2086 }
2087}
2088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002090static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091{
Mingming Yin3a941d42016-02-17 18:08:05 -08002092 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002093 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2094 out->extconn.cs.controller,
2095 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096
Mingming Yin3a941d42016-02-17 18:08:05 -08002097 reset_hdmi_sink_caps(out);
2098
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002099 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002100 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002101 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002102 out->extconn.cs.stream);
2103 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002104 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002105 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002106 }
2107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002110 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002111 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002112 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2113 case 6:
2114 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2115 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2116 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2117 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2118 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2119 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 break;
2121 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002122 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002123 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 break;
2125 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002126
2127 // check channel format caps
2128 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002129 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2130 out->extconn.cs.controller,
2131 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002132 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2133 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2134 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2135 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2136 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2137 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2138 }
2139
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002140 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2141 out->extconn.cs.controller,
2142 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002143 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2144 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2145 }
2146
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002147 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2148 out->extconn.cs.controller,
2149 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002150 ALOGV(":%s HDMI supports DTS format", __func__);
2151 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2152 }
2153
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002154 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2155 out->extconn.cs.controller,
2156 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002157 ALOGV(":%s HDMI supports DTS HD format", __func__);
2158 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2159 }
2160
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002161 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2162 out->extconn.cs.controller,
2163 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002164 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2165 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2166 }
2167
Mingming Yin3a941d42016-02-17 18:08:05 -08002168
2169 // check sample rate caps
2170 i = 0;
2171 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002172 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2173 out->extconn.cs.controller,
2174 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002175 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2176 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2177 }
2178 }
2179
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002180 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181}
2182
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002183static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2184 uint32_t *supported_sample_rates __unused,
2185 uint32_t max_rates __unused)
2186{
2187 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2188 supported_sample_rates,
2189 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302190 ssize_t i = 0;
2191
2192 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002193 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2194 supported_sample_rates[i]);
2195 }
2196 return count;
2197}
2198
2199static inline int read_usb_sup_channel_masks(bool is_playback,
2200 audio_channel_mask_t *supported_channel_masks,
2201 uint32_t max_masks)
2202{
2203 int channels = audio_extn_usb_get_max_channels(is_playback);
2204 int channel_count;
2205 uint32_t num_masks = 0;
2206 if (channels > MAX_HIFI_CHANNEL_COUNT)
2207 channels = MAX_HIFI_CHANNEL_COUNT;
2208
2209 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002210 // start from 2 channels as framework currently doesn't support mono.
2211 if (channels >= FCC_2) {
2212 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2213 }
2214 for (channel_count = FCC_2;
2215 channel_count <= channels && num_masks < max_masks;
2216 ++channel_count) {
2217 supported_channel_masks[num_masks++] =
2218 audio_channel_mask_for_index_assignment_from_count(channel_count);
2219 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002220 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002221 // For capture we report all supported channel masks from 1 channel up.
2222 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002223 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2224 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002225 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2226 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2227 if (channel_count <= FCC_2) {
2228 mask = audio_channel_in_mask_from_count(channel_count);
2229 supported_channel_masks[num_masks++] = mask;
2230 }
2231 const audio_channel_mask_t index_mask =
2232 audio_channel_mask_for_index_assignment_from_count(channel_count);
2233 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2234 supported_channel_masks[num_masks++] = index_mask;
2235 }
2236 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002237 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302238
vincenttewf51c94e2019-05-07 10:28:53 +08002239 for (size_t i = 0; i < num_masks; ++i) {
2240 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2241 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302242 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002243 return num_masks;
2244}
2245
2246static inline int read_usb_sup_formats(bool is_playback __unused,
2247 audio_format_t *supported_formats,
2248 uint32_t max_formats __unused)
2249{
2250 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2251 switch (bitwidth) {
2252 case 24:
2253 // XXX : usb.c returns 24 for s24 and s24_le?
2254 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2255 break;
2256 case 32:
2257 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2258 break;
2259 case 16:
2260 default :
2261 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2262 break;
2263 }
2264 ALOGV("%s: %s supported format %d", __func__,
2265 is_playback ? "P" : "C", bitwidth);
2266 return 1;
2267}
2268
2269static inline int read_usb_sup_params_and_compare(bool is_playback,
2270 audio_format_t *format,
2271 audio_format_t *supported_formats,
2272 uint32_t max_formats,
2273 audio_channel_mask_t *mask,
2274 audio_channel_mask_t *supported_channel_masks,
2275 uint32_t max_masks,
2276 uint32_t *rate,
2277 uint32_t *supported_sample_rates,
2278 uint32_t max_rates) {
2279 int ret = 0;
2280 int num_formats;
2281 int num_masks;
2282 int num_rates;
2283 int i;
2284
2285 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2286 max_formats);
2287 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2288 max_masks);
2289
2290 num_rates = read_usb_sup_sample_rates(is_playback,
2291 supported_sample_rates, max_rates);
2292
2293#define LUT(table, len, what, dflt) \
2294 for (i=0; i<len && (table[i] != what); i++); \
2295 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2296
2297 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2298 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2299 LUT(supported_sample_rates, num_rates, *rate, 0);
2300
2301#undef LUT
2302 return ret < 0 ? -EINVAL : 0; // HACK TBD
2303}
2304
Alexy Josephb1379942016-01-29 15:49:38 -08002305audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002306 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002307{
2308 struct audio_usecase *usecase;
2309 struct listnode *node;
2310
2311 list_for_each(node, &adev->usecase_list) {
2312 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002313 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002314 ALOGV("%s: usecase id %d", __func__, usecase->id);
2315 return usecase->id;
2316 }
2317 }
2318 return USECASE_INVALID;
2319}
2320
Alexy Josephb1379942016-01-29 15:49:38 -08002321struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002322 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002323{
2324 struct audio_usecase *usecase;
2325 struct listnode *node;
2326
2327 list_for_each(node, &adev->usecase_list) {
2328 usecase = node_to_item(node, struct audio_usecase, list);
2329 if (usecase->id == uc_id)
2330 return usecase;
2331 }
2332 return NULL;
2333}
2334
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302335/*
2336 * is a true native playback active
2337 */
2338bool audio_is_true_native_stream_active(struct audio_device *adev)
2339{
2340 bool active = false;
2341 int i = 0;
2342 struct listnode *node;
2343
2344 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2345 ALOGV("%s:napb: not in true mode or non hdphones device",
2346 __func__);
2347 active = false;
2348 goto exit;
2349 }
2350
2351 list_for_each(node, &adev->usecase_list) {
2352 struct audio_usecase *uc;
2353 uc = node_to_item(node, struct audio_usecase, list);
2354 struct stream_out *curr_out =
2355 (struct stream_out*) uc->stream.out;
2356
2357 if (curr_out && PCM_PLAYBACK == uc->type) {
2358 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2359 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2360 uc->id, curr_out->sample_rate,
2361 curr_out->bit_width,
2362 platform_get_snd_device_name(uc->out_snd_device));
2363
2364 if (is_offload_usecase(uc->id) &&
2365 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2366 active = true;
2367 ALOGD("%s:napb:native stream detected", __func__);
2368 }
2369 }
2370 }
2371exit:
2372 return active;
2373}
2374
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002375uint32_t adev_get_dsp_bit_width_enforce_mode()
2376{
2377 if (adev == NULL) {
2378 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2379 return 0;
2380 }
2381 return adev->dsp_bit_width_enforce_mode;
2382}
2383
2384static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2385{
2386 char value[PROPERTY_VALUE_MAX];
2387 int trial;
2388 uint32_t dsp_bit_width_enforce_mode = 0;
2389
2390 if (!mixer) {
2391 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2392 __func__);
2393 return 0;
2394 }
2395
2396 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2397 value, NULL) > 0) {
2398 trial = atoi(value);
2399 switch (trial) {
2400 case 16:
2401 dsp_bit_width_enforce_mode = 16;
2402 break;
2403 case 24:
2404 dsp_bit_width_enforce_mode = 24;
2405 break;
2406 case 32:
2407 dsp_bit_width_enforce_mode = 32;
2408 break;
2409 default:
2410 dsp_bit_width_enforce_mode = 0;
2411 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2412 break;
2413 }
2414 }
2415
2416 return dsp_bit_width_enforce_mode;
2417}
2418
2419static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2420 uint32_t enforce_mode,
2421 bool enable)
2422{
2423 struct mixer_ctl *ctl = NULL;
2424 const char *mixer_ctl_name = "ASM Bit Width";
2425 uint32_t asm_bit_width_mode = 0;
2426
2427 if (enforce_mode == 0) {
2428 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2429 return;
2430 }
2431
2432 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2433 if (!ctl) {
2434 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2435 __func__, mixer_ctl_name);
2436 return;
2437 }
2438
2439 if (enable)
2440 asm_bit_width_mode = enforce_mode;
2441 else
2442 asm_bit_width_mode = 0;
2443
2444 ALOGV("%s DSP bit width feature status is %d width=%d",
2445 __func__, enable, asm_bit_width_mode);
2446 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2447 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2448 asm_bit_width_mode);
2449
2450 return;
2451}
2452
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302453/*
2454 * if native DSD playback active
2455 */
2456bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2457{
2458 bool active = false;
2459 struct listnode *node = NULL;
2460 struct audio_usecase *uc = NULL;
2461 struct stream_out *curr_out = NULL;
2462
2463 list_for_each(node, &adev->usecase_list) {
2464 uc = node_to_item(node, struct audio_usecase, list);
2465 curr_out = (struct stream_out*) uc->stream.out;
2466
2467 if (curr_out && PCM_PLAYBACK == uc->type &&
2468 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2469 active = true;
2470 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302471 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302472 }
2473 }
2474 return active;
2475}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302476
2477static bool force_device_switch(struct audio_usecase *usecase)
2478{
2479 bool ret = false;
2480 bool is_it_true_mode = false;
2481
Zhou Song30f2c3e2018-02-08 14:02:15 +08002482 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302483 usecase->type == TRANSCODE_LOOPBACK_RX ||
2484 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002485 return false;
2486 }
2487
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002488 if(usecase->stream.out == NULL) {
2489 ALOGE("%s: stream.out is NULL", __func__);
2490 return false;
2491 }
2492
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302493 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002494 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002495 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2496 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302497 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2498 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2499 (!is_it_true_mode && adev->native_playback_enabled)){
2500 ret = true;
2501 ALOGD("napb: time to toggle native mode");
2502 }
2503 }
2504
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302505 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302506 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2507 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002508 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302509 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302510 ALOGD("Force a2dp device switch to update new encoder config");
2511 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002512 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302513
Florian Pfister1a84f312018-07-19 14:38:18 +02002514 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302515 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2516 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002517 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302518 return ret;
2519}
2520
Aalique Grahame22e49102018-12-18 14:23:57 -08002521static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2522{
2523 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2524}
2525
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302526bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2527{
2528 bool ret=false;
2529 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002530 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2531 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302532 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2533 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002534 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302535 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002536 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2537 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302538 ret = true;
2539
2540 return ret;
2541}
2542
2543bool is_a2dp_device(snd_device_t out_snd_device)
2544{
2545 bool ret=false;
2546 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2547 ret = true;
2548
2549 return ret;
2550}
2551
2552bool is_bt_soc_on(struct audio_device *adev)
2553{
2554 struct mixer_ctl *ctl;
2555 char *mixer_ctl_name = "BT SOC status";
2556 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2557 bool bt_soc_status = true;
2558 if (!ctl) {
2559 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2560 __func__, mixer_ctl_name);
2561 /*This is to ensure we dont break targets which dont have the kernel change*/
2562 return true;
2563 }
2564 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2565 ALOGD("BT SOC status: %d",bt_soc_status);
2566 return bt_soc_status;
2567}
2568
Zhou Song331c8e52019-08-26 14:16:12 +08002569static int configure_btsco_sample_rate(snd_device_t snd_device)
2570{
2571 struct mixer_ctl *ctl = NULL;
2572 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2573 char *rate_str = NULL;
2574 bool is_rx_dev = true;
2575
2576 if (is_btsco_device(snd_device, snd_device)) {
2577 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2578 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2579 if (!ctl_sr_tx || !ctl_sr_rx) {
2580 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2581 if (!ctl_sr)
2582 return -ENOSYS;
2583 }
2584
2585 switch (snd_device) {
2586 case SND_DEVICE_OUT_BT_SCO:
2587 rate_str = "KHZ_8";
2588 break;
2589 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2590 case SND_DEVICE_IN_BT_SCO_MIC:
2591 rate_str = "KHZ_8";
2592 is_rx_dev = false;
2593 break;
2594 case SND_DEVICE_OUT_BT_SCO_WB:
2595 rate_str = "KHZ_16";
2596 break;
2597 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2598 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2599 rate_str = "KHZ_16";
2600 is_rx_dev = false;
2601 break;
2602 default:
2603 return 0;
2604 }
2605
2606 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2607 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2608 return -ENOSYS;
2609 }
2610 return 0;
2611}
2612
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302613int out_standby_l(struct audio_stream *stream);
2614
Eric Laurent637e2d42018-11-15 12:24:31 -08002615struct stream_in *adev_get_active_input(const struct audio_device *adev)
2616{
2617 struct listnode *node;
2618 struct stream_in *last_active_in = NULL;
2619
2620 /* Get last added active input.
2621 * TODO: We may use a priority mechanism to pick highest priority active source */
2622 list_for_each(node, &adev->usecase_list)
2623 {
2624 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2625 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2626 last_active_in = usecase->stream.in;
2627 }
2628
2629 return last_active_in;
2630}
2631
2632struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2633{
2634 struct listnode *node;
2635
2636 /* First check active inputs with voice communication source and then
2637 * any input if audio mode is in communication */
2638 list_for_each(node, &adev->usecase_list)
2639 {
2640 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2641 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2642 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2643 return usecase->stream.in;
2644 }
2645 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2646 return adev_get_active_input(adev);
2647
2648 return NULL;
2649}
2650
Carter Hsu2e429db2019-05-14 18:50:52 +08002651/*
2652 * Aligned with policy.h
2653 */
2654static inline int source_priority(int inputSource)
2655{
2656 switch (inputSource) {
2657 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2658 return 9;
2659 case AUDIO_SOURCE_CAMCORDER:
2660 return 8;
2661 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2662 return 7;
2663 case AUDIO_SOURCE_UNPROCESSED:
2664 return 6;
2665 case AUDIO_SOURCE_MIC:
2666 return 5;
2667 case AUDIO_SOURCE_ECHO_REFERENCE:
2668 return 4;
2669 case AUDIO_SOURCE_FM_TUNER:
2670 return 3;
2671 case AUDIO_SOURCE_VOICE_RECOGNITION:
2672 return 2;
2673 case AUDIO_SOURCE_HOTWORD:
2674 return 1;
2675 default:
2676 break;
2677 }
2678 return 0;
2679}
2680
2681static struct stream_in *get_priority_input(struct audio_device *adev)
2682{
2683 struct listnode *node;
2684 struct audio_usecase *usecase;
2685 int last_priority = 0, priority;
2686 struct stream_in *priority_in = NULL;
2687 struct stream_in *in;
2688
2689 list_for_each(node, &adev->usecase_list) {
2690 usecase = node_to_item(node, struct audio_usecase, list);
2691 if (usecase->type == PCM_CAPTURE) {
2692 in = usecase->stream.in;
2693 if (!in)
2694 continue;
2695 priority = source_priority(in->source);
2696
2697 if (priority > last_priority) {
2698 last_priority = priority;
2699 priority_in = in;
2700 }
2701 }
2702 }
2703 return priority_in;
2704}
2705
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002706int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002708 snd_device_t out_snd_device = SND_DEVICE_NONE;
2709 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002710 struct audio_usecase *usecase = NULL;
2711 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002712 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002713 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302714 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002715 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002716 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302718 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2719
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002720 usecase = get_usecase_from_list(adev, uc_id);
2721 if (usecase == NULL) {
2722 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2723 return -EINVAL;
2724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002726 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002727 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002728 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002729 (usecase->type == ICC_CALL) ||
2730 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302731 if(usecase->stream.out == NULL) {
2732 ALOGE("%s: stream.out is NULL", __func__);
2733 return -EINVAL;
2734 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002735 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002736 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2737 uc_id);
2738 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2739 uc_id);
2740 } else {
2741 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302742 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002743 in_snd_device = platform_get_input_snd_device(adev->platform,
2744 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302745 &usecase->stream.out->device_list,
2746 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002747 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002748 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302749 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302750 if (usecase->stream.inout == NULL) {
2751 ALOGE("%s: stream.inout is NULL", __func__);
2752 return -EINVAL;
2753 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002754 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302755 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2756 stream_out.format = usecase->stream.inout->out_config.format;
2757 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302758 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 assign_devices(&usecase->device_list,
2760 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302761 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2762 if (usecase->stream.inout == NULL) {
2763 ALOGE("%s: stream.inout is NULL", __func__);
2764 return -EINVAL;
2765 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302766 struct listnode out_devices;
2767 list_init(&out_devices);
2768 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2769 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002770 assign_devices(&usecase->device_list,
2771 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002772 } else {
2773 /*
2774 * If the voice call is active, use the sound devices of voice call usecase
2775 * so that it would not result any device switch. All the usecases will
2776 * be switched to new device when select_devices() is called for voice call
2777 * usecase. This is to avoid switching devices for voice call when
2778 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002779 * choose voice call device only if the use case device is
2780 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002781 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002782 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002783 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002784 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002785 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2786 is_codec_backend_out_device_type(&usecase->device_list)) ||
2787 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2788 is_codec_backend_in_device_type(&usecase->device_list)) ||
2789 is_single_device_type_equal(&vc_usecase->device_list,
2790 AUDIO_DEVICE_OUT_HEARING_AID) ||
2791 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002792 AUDIO_DEVICE_IN_VOICE_CALL) ||
2793 (is_single_device_type_equal(&usecase->device_list,
2794 AUDIO_DEVICE_IN_USB_HEADSET) &&
2795 is_single_device_type_equal(&vc_usecase->device_list,
2796 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002797 in_snd_device = vc_usecase->in_snd_device;
2798 out_snd_device = vc_usecase->out_snd_device;
2799 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002800 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002801 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002802 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002803 if ((voip_usecase != NULL) &&
2804 (usecase->type == PCM_PLAYBACK) &&
2805 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002806 out_snd_device_backend_match = platform_check_backends_match(
2807 voip_usecase->out_snd_device,
2808 platform_get_output_snd_device(
2809 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302810 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002811 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002812 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2813 (is_codec_backend_out_device_type(&usecase->device_list) ||
2814 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002815 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002816 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002817 in_snd_device = voip_usecase->in_snd_device;
2818 out_snd_device = voip_usecase->out_snd_device;
2819 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002820 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002821 hfp_ucid = audio_extn_hfp_get_usecase();
2822 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002823 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002824 in_snd_device = hfp_usecase->in_snd_device;
2825 out_snd_device = hfp_usecase->out_snd_device;
2826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002827 }
2828 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302829 if (usecase->stream.out == NULL) {
2830 ALOGE("%s: stream.out is NULL", __func__);
2831 return -EINVAL;
2832 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002833 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002834 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002835 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002836 struct stream_out *voip_out = adev->primary_output;
2837 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002838 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002839 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2840 else
2841 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302842 usecase->stream.out,
2843 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002844 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002845
Eric Laurent637e2d42018-11-15 12:24:31 -08002846 if (voip_usecase)
2847 voip_out = voip_usecase->stream.out;
2848
2849 if (usecase->stream.out == voip_out && voip_in != NULL)
2850 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302853 if (usecase->stream.in == NULL) {
2854 ALOGE("%s: stream.in is NULL", __func__);
2855 return -EINVAL;
2856 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002857 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002858 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002859 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002860 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002861 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002862 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002863
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002864 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002865 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002866 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2867 USECASE_AUDIO_PLAYBACK_VOIP);
2868
Carter Hsu2e429db2019-05-14 18:50:52 +08002869 usecase->stream.in->enable_ec_port = false;
2870
Zhou Song62ea0282020-03-22 19:53:01 +08002871 bool is_ha_usecase = adev->ha_proxy_enable ?
2872 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2873 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2874 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002875 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002876 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002877 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002878 } else if (adev->primary_output &&
2879 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002880 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002881 } else {
2882 /* forcing speaker o/p device to get matching i/p pair
2883 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002884 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002885 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002886 priority_in = voip_in;
2887 } else {
2888 /* get the input with the highest priority source*/
2889 priority_in = get_priority_input(adev);
2890
2891 if (!priority_in)
2892 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002893 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002894 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2895 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2896 }
2897 else
2898 in_snd_device = platform_get_input_snd_device(adev->platform,
2899 priority_in,
2900 &out_devices,
2901 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002902 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002903 }
2904 }
2905
2906 if (out_snd_device == usecase->out_snd_device &&
2907 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302908
2909 if (!force_device_switch(usecase))
2910 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 }
2912
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002913 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002914 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002915 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002916 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2917 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302918 }
2919
Aalique Grahame22e49102018-12-18 14:23:57 -08002920 if (out_snd_device != SND_DEVICE_NONE &&
2921 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2922 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2923 __func__,
2924 use_case_table[uc_id],
2925 adev->last_logged_snd_device[uc_id][0],
2926 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2927 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2928 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2929 -1,
2930 out_snd_device,
2931 platform_get_snd_device_name(out_snd_device),
2932 platform_get_snd_device_acdb_id(out_snd_device));
2933 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2934 }
2935 if (in_snd_device != SND_DEVICE_NONE &&
2936 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2937 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2938 __func__,
2939 use_case_table[uc_id],
2940 adev->last_logged_snd_device[uc_id][1],
2941 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2942 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2943 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2944 -1,
2945 in_snd_device,
2946 platform_get_snd_device_name(in_snd_device),
2947 platform_get_snd_device_acdb_id(in_snd_device));
2948 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2949 }
2950
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 /*
2953 * Limitation: While in call, to do a device switch we need to disable
2954 * and enable both RX and TX devices though one of them is same as current
2955 * device.
2956 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002957 if ((usecase->type == VOICE_CALL) &&
2958 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2959 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002960 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002961 }
2962
2963 if (((usecase->type == VOICE_CALL) ||
2964 (usecase->type == VOIP_CALL)) &&
2965 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2966 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302967 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002968 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002969 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002970
2971 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302972 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002973 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002974 }
2975
Aalique Grahame22e49102018-12-18 14:23:57 -08002976 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2977 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002978 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302979 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002980 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2981 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2982 else
2983 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302984 }
2985
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002986 /* Disable current sound devices */
2987 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002988 disable_audio_route(adev, usecase);
2989 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 }
2991
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002992 if (usecase->in_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->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 }
2996
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002997 /* Applicable only on the targets that has external modem.
2998 * New device information should be sent to modem before enabling
2999 * the devices to reduce in-call device switch time.
3000 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003001 if ((usecase->type == VOICE_CALL) &&
3002 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3003 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003004 status = platform_switch_voice_call_enable_device_config(adev->platform,
3005 out_snd_device,
3006 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003007 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003008
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003009 /* Enable new sound devices */
3010 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003011 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303012 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303013 if (platform_check_codec_asrc_support(adev->platform))
3014 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003015 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003016 /* Enable haptics device for haptic usecase */
3017 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3018 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 }
3020
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003021 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303022 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003023 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003024 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003025
Avinash Vaish71a8b972014-07-24 15:36:33 +05303026 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07003027 status = platform_switch_voice_call_device_post(adev->platform,
3028 out_snd_device,
3029 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05303030 enable_audio_route_for_voice_usecases(adev, usecase);
3031 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003032
sangwoo170731f2013-06-08 15:36:36 +09003033 usecase->in_snd_device = in_snd_device;
3034 usecase->out_snd_device = out_snd_device;
3035
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303036 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3037 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303038 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003039 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003040 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003041 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3042 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3043 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3044 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3045 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3046 /*
3047 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3048 * configured device sample rate, if not update the COPP rate to be equal to the
3049 * device sample rate, else open COPP at stream sample rate
3050 */
3051 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3052 usecase->stream.out->sample_rate,
3053 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303054 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303055 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3056 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303057 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003058 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3059 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3060 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3061 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003062 }
3063 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003064
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003065 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003066
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003067 /* If input stream is already running then effect needs to be
3068 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003069 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003070 check_and_enable_effect(adev);
3071
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003072 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003073 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303074 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003075 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3076
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003077 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303078 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003079 voice_extn_compress_voip_is_started(adev))
3080 voice_set_sidetone(adev, out_snd_device, true);
3081 }
3082
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003083 /* Applicable only on the targets that has external modem.
3084 * Enable device command should be sent to modem only after
3085 * enabling voice call mixer controls
3086 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003087 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003088 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3089 out_snd_device,
3090 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303091
3092 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003093 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303094 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003095 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303096 if (is_bt_soc_on(adev) == false){
3097 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003098 if (in->pcm != NULL)
3099 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303100 }
3101 }
3102 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3103 && usecase->stream.out->started) {
3104 if (is_bt_soc_on(adev) == false) {
3105 ALOGD("BT SCO/A2DP disconnected while in connection");
3106 out_standby_l(&usecase->stream.out->stream.common);
3107 }
3108 }
3109 } else if ((usecase->stream.out != NULL) &&
3110 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303111 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3112 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003113 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303114 usecase->stream.out->started) {
3115 if (is_bt_soc_on(adev) == false) {
3116 ALOGD("BT SCO/A2dp disconnected while in connection");
3117 out_standby_l(&usecase->stream.out->stream.common);
3118 }
3119 }
3120 }
3121
Yung Ti Su70cb8242018-06-22 17:38:47 +08003122 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003123 struct stream_out *voip_out = voip_usecase->stream.out;
3124 audio_extn_utils_send_app_type_gain(adev,
3125 voip_out->app_type_cfg.app_type,
3126 &voip_out->app_type_cfg.gain[0]);
3127 }
3128
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003129 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 return status;
3132}
3133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134static int stop_input_stream(struct stream_in *in)
3135{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303136 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303138
3139 if (in == NULL) {
3140 ALOGE("%s: stream_in ptr is NULL", __func__);
3141 return -EINVAL;
3142 }
3143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003145 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Eric Laurent994a6932013-07-17 11:51:42 -07003147 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003148 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 uc_info = get_usecase_from_list(adev, in->usecase);
3150 if (uc_info == NULL) {
3151 ALOGE("%s: Could not find the usecase (%d) in the list",
3152 __func__, in->usecase);
3153 return -EINVAL;
3154 }
3155
Carter Hsu2e429db2019-05-14 18:50:52 +08003156 priority_in = get_priority_input(adev);
3157
Derek Chenea197282019-01-07 17:35:01 -08003158 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3159 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003160
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003161 /* Close in-call recording streams */
3162 voice_check_and_stop_incall_rec_usecase(adev, in);
3163
Eric Laurent150dbfe2013-02-27 14:31:02 -08003164 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003165 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003166
3167 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003168 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003170 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303171 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3172
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003173 list_remove(&uc_info->list);
3174 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175
Carter Hsu2e429db2019-05-14 18:50:52 +08003176 if (priority_in == in) {
3177 priority_in = get_priority_input(adev);
3178 if (priority_in)
3179 select_devices(adev, priority_in->usecase);
3180 }
3181
Vatsal Buchac09ae062018-11-14 13:25:08 +05303182 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003183 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 return ret;
3185}
3186
3187int start_input_stream(struct stream_in *in)
3188{
3189 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003190 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303192
3193 if (in == NULL) {
3194 ALOGE("%s: stream_in ptr is NULL", __func__);
3195 return -EINVAL;
3196 }
3197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003199 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003200 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201
Mingming Yin2664a5b2015-09-03 10:53:11 -07003202 if (get_usecase_from_list(adev, usecase) == NULL)
3203 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303204 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3205 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003206
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303207 if (CARD_STATUS_OFFLINE == in->card_status||
3208 CARD_STATUS_OFFLINE == adev->card_status) {
3209 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303210 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303211 goto error_config;
3212 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303213
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003214 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303215 if (!adev->bt_sco_on) {
3216 ALOGE("%s: SCO profile is not ready, return error", __func__);
3217 ret = -EIO;
3218 goto error_config;
3219 }
3220 }
3221
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003222 /* Check if source matches incall recording usecase criteria */
3223 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3224 if (ret)
3225 goto error_config;
3226 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003227 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3228
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303229 if (audio_extn_cin_attached_usecase(in))
3230 audio_extn_cin_acquire_usecase(in);
3231
Mingming Yin2664a5b2015-09-03 10:53:11 -07003232 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3233 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3234 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003235 ret = -EINVAL;
3236 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003237 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003238
Eric Laurentb23d5282013-05-14 15:27:20 -07003239 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 if (in->pcm_device_id < 0) {
3241 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3242 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003243 ret = -EINVAL;
3244 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003248
3249 if (!uc_info) {
3250 ret = -ENOMEM;
3251 goto error_config;
3252 }
3253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 uc_info->id = in->usecase;
3255 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003256 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003257 list_init(&uc_info->device_list);
3258 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003259 uc_info->in_snd_device = SND_DEVICE_NONE;
3260 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003262 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003263 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303264 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3265 adev->perf_lock_opts,
3266 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003267 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268
Derek Chenea197282019-01-07 17:35:01 -08003269 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3270 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003271
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303272 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3273
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303274 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303275 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303276 if (ret)
3277 goto error_open;
3278 else
3279 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003280 }
3281
Haynes Mathew George16081042017-05-31 17:16:49 -07003282 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003283 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003284 ALOGE("%s: pcm stream not ready", __func__);
3285 goto error_open;
3286 }
3287 ret = pcm_start(in->pcm);
3288 if (ret < 0) {
3289 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3290 goto error_open;
3291 }
3292 } else {
3293 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3294 unsigned int pcm_open_retry_count = 0;
3295
Zhou Song62ea0282020-03-22 19:53:01 +08003296 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3297 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003298 flags |= PCM_MMAP | PCM_NOIRQ;
3299 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3300 } else if (in->realtime) {
3301 flags |= PCM_MMAP | PCM_NOIRQ;
3302 }
3303
Garmond Leunge2433c32017-09-28 21:51:22 -07003304 if (audio_extn_ffv_get_stream() == in) {
3305 ALOGD("%s: ffv stream, update pcm config", __func__);
3306 audio_extn_ffv_update_pcm_config(&config);
3307 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003308 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3309 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3310
3311 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003312 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003313 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003314 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003315 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303316 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303317 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3318 adev->card_status = CARD_STATUS_OFFLINE;
3319 in->card_status = CARD_STATUS_OFFLINE;
3320 ret = -EIO;
3321 goto error_open;
3322 }
3323
Haynes Mathew George16081042017-05-31 17:16:49 -07003324 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3325 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3326 if (in->pcm != NULL) {
3327 pcm_close(in->pcm);
3328 in->pcm = NULL;
3329 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003330 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003331 ret = -EIO;
3332 goto error_open;
3333 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003334 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003335 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3336 continue;
3337 }
3338 break;
3339 }
3340
3341 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003342 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003343 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003344 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003345 if (ret < 0) {
3346 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3347 pcm_close(in->pcm);
3348 in->pcm = NULL;
3349 goto error_open;
3350 }
3351 register_in_stream(in);
3352 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003353 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003354 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003355 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003356 if (ret < 0) {
3357 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003358 pcm_close(in->pcm);
3359 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003360 goto error_open;
3361 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003362 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003363 }
3364
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003365 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003366 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3367 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003368
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003369 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303370 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3371
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303372done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003373 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303374 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303375 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303376 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003377 return ret;
3378
3379error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003380 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303381 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003383
Eric Laurentc8400632013-02-14 19:04:54 -08003384error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003385 if (audio_extn_cin_attached_usecase(in))
3386 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303387 /*
3388 * sleep 50ms to allow sufficient time for kernel
3389 * drivers to recover incases like SSR.
3390 */
3391 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003392 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303393 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003394 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395}
3396
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003397void lock_input_stream(struct stream_in *in)
3398{
3399 pthread_mutex_lock(&in->pre_lock);
3400 pthread_mutex_lock(&in->lock);
3401 pthread_mutex_unlock(&in->pre_lock);
3402}
3403
3404void lock_output_stream(struct stream_out *out)
3405{
3406 pthread_mutex_lock(&out->pre_lock);
3407 pthread_mutex_lock(&out->lock);
3408 pthread_mutex_unlock(&out->pre_lock);
3409}
3410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003411/* must be called with out->lock locked */
3412static int send_offload_cmd_l(struct stream_out* out, int command)
3413{
3414 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3415
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003416 if (!cmd) {
3417 ALOGE("failed to allocate mem for command 0x%x", command);
3418 return -ENOMEM;
3419 }
3420
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003421 ALOGVV("%s %d", __func__, command);
3422
3423 cmd->cmd = command;
3424 list_add_tail(&out->offload_cmd_list, &cmd->node);
3425 pthread_cond_signal(&out->offload_cond);
3426 return 0;
3427}
3428
Weiyin Jiang280ea742020-09-08 20:28:22 +08003429/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430static void stop_compressed_output_l(struct stream_out *out)
3431{
3432 out->offload_state = OFFLOAD_STATE_IDLE;
3433 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003434 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 if (out->compr != NULL) {
3436 compress_stop(out->compr);
3437 while (out->offload_thread_blocked) {
3438 pthread_cond_wait(&out->cond, &out->lock);
3439 }
3440 }
3441}
3442
Varun Balaraje49253e2017-07-06 19:48:56 +05303443bool is_interactive_usecase(audio_usecase_t uc_id)
3444{
3445 unsigned int i;
3446 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3447 if (uc_id == interactive_usecases[i])
3448 return true;
3449 }
3450 return false;
3451}
3452
3453static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3454{
3455 audio_usecase_t ret_uc = USECASE_INVALID;
3456 unsigned int intract_uc_index;
3457 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3458
3459 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3460 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3461 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3462 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3463 ret_uc = interactive_usecases[intract_uc_index];
3464 break;
3465 }
3466 }
3467
3468 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3469 return ret_uc;
3470}
3471
3472static void free_interactive_usecase(struct audio_device *adev,
3473 audio_usecase_t uc_id)
3474{
3475 unsigned int interact_uc_index;
3476 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3477
3478 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3479 if (interactive_usecases[interact_uc_index] == uc_id) {
3480 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3481 break;
3482 }
3483 }
3484 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3485}
3486
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003487bool is_offload_usecase(audio_usecase_t uc_id)
3488{
3489 unsigned int i;
3490 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3491 if (uc_id == offload_usecases[i])
3492 return true;
3493 }
3494 return false;
3495}
3496
Dhananjay Kumarac341582017-02-23 23:42:25 +05303497static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003498{
vivek mehta446c3962015-09-14 10:57:35 -07003499 audio_usecase_t ret_uc = USECASE_INVALID;
3500 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003501 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003502 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303503 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003504 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3505 else
3506 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003507
vivek mehta446c3962015-09-14 10:57:35 -07003508 pthread_mutex_lock(&adev->lock);
3509 if (get_usecase_from_list(adev, ret_uc) != NULL)
3510 ret_uc = USECASE_INVALID;
3511 pthread_mutex_unlock(&adev->lock);
3512
3513 return ret_uc;
3514 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003515
3516 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003517 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3518 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3519 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3520 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003521 break;
3522 }
3523 }
vivek mehta446c3962015-09-14 10:57:35 -07003524
3525 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3526 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003527}
3528
3529static void free_offload_usecase(struct audio_device *adev,
3530 audio_usecase_t uc_id)
3531{
vivek mehta446c3962015-09-14 10:57:35 -07003532 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003533 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003534
3535 if (!adev->multi_offload_enable)
3536 return;
3537
3538 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3539 if (offload_usecases[offload_uc_index] == uc_id) {
3540 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003541 break;
3542 }
3543 }
3544 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3545}
3546
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547static void *offload_thread_loop(void *context)
3548{
3549 struct stream_out *out = (struct stream_out *) context;
3550 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003551 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003554 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3556
3557 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003558 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003559 out->offload_state = OFFLOAD_STATE_IDLE;
3560 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003561 for (;;) {
3562 struct offload_cmd *cmd = NULL;
3563 stream_callback_event_t event;
3564 bool send_callback = false;
3565
3566 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3567 __func__, list_empty(&out->offload_cmd_list),
3568 out->offload_state);
3569 if (list_empty(&out->offload_cmd_list)) {
3570 ALOGV("%s SLEEPING", __func__);
3571 pthread_cond_wait(&out->offload_cond, &out->lock);
3572 ALOGV("%s RUNNING", __func__);
3573 continue;
3574 }
3575
3576 item = list_head(&out->offload_cmd_list);
3577 cmd = node_to_item(item, struct offload_cmd, node);
3578 list_remove(item);
3579
3580 ALOGVV("%s STATE %d CMD %d out->compr %p",
3581 __func__, out->offload_state, cmd->cmd, out->compr);
3582
3583 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3584 free(cmd);
3585 break;
3586 }
3587
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003588 // allow OFFLOAD_CMD_ERROR reporting during standby
3589 // this is needed to handle failures during compress_open
3590 // Note however that on a pause timeout, the stream is closed
3591 // and no offload usecase will be active. Therefore this
3592 // special case is needed for compress_open failures alone
3593 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3594 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003595 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003596 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003597 pthread_cond_signal(&out->cond);
3598 continue;
3599 }
3600 out->offload_thread_blocked = true;
3601 pthread_mutex_unlock(&out->lock);
3602 send_callback = false;
3603 switch(cmd->cmd) {
3604 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003605 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003606 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003607 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608 send_callback = true;
3609 event = STREAM_CBK_EVENT_WRITE_READY;
3610 break;
3611 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003612 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303613 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003614 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303615 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003616 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303617 if (ret < 0)
3618 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303619 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303620 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003621 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003622 else
3623 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003624 if (-ENETRESET != ret && !(-EINTR == ret &&
3625 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303626 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303627 pthread_mutex_lock(&out->lock);
3628 out->send_new_metadata = 1;
3629 out->send_next_track_params = true;
3630 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303631 event = STREAM_CBK_EVENT_DRAIN_READY;
3632 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3633 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303634 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003635 break;
3636 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003637 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003638 ret = compress_drain(out->compr);
3639 ALOGD("copl(%p):out of compress_drain", out);
3640 // EINTR check avoids drain interruption due to SSR
3641 if (-ENETRESET != ret && !(-EINTR == ret &&
3642 CARD_STATUS_OFFLINE == out->card_status)) {
3643 send_callback = true;
3644 event = STREAM_CBK_EVENT_DRAIN_READY;
3645 } else
3646 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003647 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303648 case OFFLOAD_CMD_ERROR:
3649 ALOGD("copl(%p): sending error callback to AF", out);
3650 send_callback = true;
3651 event = STREAM_CBK_EVENT_ERROR;
3652 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653 default:
3654 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3655 break;
3656 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003657 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658 out->offload_thread_blocked = false;
3659 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003660 if (send_callback && out->client_callback) {
3661 ALOGVV("%s: sending client_callback event %d", __func__, event);
3662 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003663 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 free(cmd);
3665 }
3666
3667 pthread_cond_signal(&out->cond);
3668 while (!list_empty(&out->offload_cmd_list)) {
3669 item = list_head(&out->offload_cmd_list);
3670 list_remove(item);
3671 free(node_to_item(item, struct offload_cmd, node));
3672 }
3673 pthread_mutex_unlock(&out->lock);
3674
3675 return NULL;
3676}
3677
3678static int create_offload_callback_thread(struct stream_out *out)
3679{
3680 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3681 list_init(&out->offload_cmd_list);
3682 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3683 offload_thread_loop, out);
3684 return 0;
3685}
3686
3687static int destroy_offload_callback_thread(struct stream_out *out)
3688{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003689 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08003690 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 stop_compressed_output_l(out);
3692 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3693
Weiyin Jiang280ea742020-09-08 20:28:22 +08003694 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003695 pthread_mutex_unlock(&out->lock);
3696 pthread_join(out->offload_thread, (void **) NULL);
3697 pthread_cond_destroy(&out->offload_cond);
3698
3699 return 0;
3700}
3701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702static int stop_output_stream(struct stream_out *out)
3703{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303704 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 struct audio_usecase *uc_info;
3706 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003707 bool has_voip_usecase =
3708 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709
Eric Laurent994a6932013-07-17 11:51:42 -07003710 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003711 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 uc_info = get_usecase_from_list(adev, out->usecase);
3713 if (uc_info == NULL) {
3714 ALOGE("%s: Could not find the usecase (%d) in the list",
3715 __func__, out->usecase);
3716 return -EINVAL;
3717 }
3718
Derek Chenea197282019-01-07 17:35:01 -08003719 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3720 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003721
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003722 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303723 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003724 if (adev->visualizer_stop_output != NULL)
3725 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003726
3727 audio_extn_dts_remove_state_notifier_node(out->usecase);
3728
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 if (adev->offload_effects_stop_output != NULL)
3730 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003731 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3732 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3733 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003734 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003735
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003736 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3737 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003738 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003739 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003740
Eric Laurent150dbfe2013-02-27 14:31:02 -08003741 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003742 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003743
3744 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003745 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003746 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3747 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748
Aalique Grahame22e49102018-12-18 14:23:57 -08003749 audio_extn_extspk_update(adev->extspk);
3750
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003751 if (is_offload_usecase(out->usecase)) {
3752 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3753 adev->dsp_bit_width_enforce_mode,
3754 false);
3755 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003756 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003757 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3758 false);
3759
3760 if (ret != 0)
3761 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3762 /* default service interval was successfully updated,
3763 reopen USB backend with new service interval */
3764 ret = 0;
3765 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003766
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003767 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303768 out->started = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08003769 pthread_mutex_lock(&out->latch_lock);
3770 out->muted = false;
3771 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003772 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303773 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003774 ALOGV("Disable passthrough , reset mixer to pcm");
3775 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003776#ifdef AUDIO_GKI_ENABLED
3777 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3778 out->compr_config.codec->reserved[0] = 0;
3779#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003780 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003781#endif
Mingming Yin21854652016-04-13 11:54:02 -07003782 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003783 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3784 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003785
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303786 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003787 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303788 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303789
Manish Dewangan21a850a2017-08-14 12:03:55 +05303790 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003791 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3792 if (ret < 0)
3793 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3794 }
3795
juyuchen2d415992018-11-16 14:15:16 +08003796 /* 1) media + voip output routing to handset must route media back to
3797 speaker when voip stops.
3798 2) trigger voip input to reroute when voip output changes to
3799 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003800 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003801 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003802 struct listnode *node;
3803 struct audio_usecase *usecase;
3804 list_for_each(node, &adev->usecase_list) {
3805 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003806 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303807 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3808 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003809 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003810 continue;
3811
3812 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3813 __func__, usecase->id, use_case_table[usecase->id],
3814 out->usecase, use_case_table[out->usecase]);
3815 select_devices(adev, usecase->id);
3816 }
3817 }
3818
Garmond Leung5fd0b552018-04-17 11:56:12 -07003819 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003820 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 return ret;
3822}
3823
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003824struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3825 unsigned int flags, unsigned int pcm_open_retry_count,
3826 struct pcm_config *config)
3827{
3828 struct pcm* pcm = NULL;
3829
3830 while (1) {
3831 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3832 if (pcm == NULL || !pcm_is_ready(pcm)) {
3833 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3834 if (pcm != NULL) {
3835 pcm_close(pcm);
3836 pcm = NULL;
3837 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003838 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003839 return NULL;
3840
Weiyin Jiang72197252019-10-09 11:49:32 +08003841 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003842 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3843 continue;
3844 }
3845 break;
3846 }
3847
3848 if (pcm_is_ready(pcm)) {
3849 int ret = pcm_prepare(pcm);
3850 if (ret < 0) {
3851 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3852 pcm_close(pcm);
3853 pcm = NULL;
3854 }
3855 }
3856
3857 return pcm;
3858}
3859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860int start_output_stream(struct stream_out *out)
3861{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 struct audio_usecase *uc_info;
3864 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003865 char mixer_ctl_name[128];
3866 struct mixer_ctl *ctl = NULL;
3867 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303868 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003869 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870
Haynes Mathew George380745d2017-10-04 15:27:45 -07003871 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003872 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3873 ret = -EINVAL;
3874 goto error_config;
3875 }
3876
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003877 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303878 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003879 get_device_types(&out->device_list), is_haptic_usecase);
3880
3881 bool is_speaker_active = compare_device_type(&out->device_list,
3882 AUDIO_DEVICE_OUT_SPEAKER);
3883 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3884 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303885
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303886 if (CARD_STATUS_OFFLINE == out->card_status ||
3887 CARD_STATUS_OFFLINE == adev->card_status) {
3888 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303889 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003890 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303891 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303892
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003893 //Update incall music usecase to reflect correct voice session
3894 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3895 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3896 if (ret != 0) {
3897 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3898 __func__, ret);
3899 goto error_config;
3900 }
3901 }
3902
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003903 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003904 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003905 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303906 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303907 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003908 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303909 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3910 ret = -EAGAIN;
3911 goto error_config;
3912 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303913 }
3914 }
3915 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003916 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303917 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003918 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303919 //combo usecase just by pass a2dp
3920 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003921 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303922 } else {
3923 ALOGE("%s: SCO profile is not ready, return error", __func__);
3924 ret = -EAGAIN;
3925 goto error_config;
3926 }
3927 }
3928 }
3929
Eric Laurentb23d5282013-05-14 15:27:20 -07003930 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 if (out->pcm_device_id < 0) {
3932 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3933 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003934 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003935 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 }
3937
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003938 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003939 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3940 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003941 if (adev->haptic_pcm_device_id < 0) {
3942 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3943 __func__, adev->haptic_pcm_device_id, out->usecase);
3944 ret = -EINVAL;
3945 goto error_config;
3946 }
3947 }
3948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003950
3951 if (!uc_info) {
3952 ret = -ENOMEM;
3953 goto error_config;
3954 }
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 uc_info->id = out->usecase;
3957 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003958 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003959 list_init(&uc_info->device_list);
3960 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003961 uc_info->in_snd_device = SND_DEVICE_NONE;
3962 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003963
3964 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003965 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003966 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3967 /* USB backend is not reopened immediately.
3968 This is eventually done as part of select_devices */
3969 }
3970
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003971 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972
Wei Wangf7ca6c92017-11-21 14:51:20 -08003973 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303974 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3975 adev->perf_lock_opts,
3976 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303977
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003978 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303979 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303980 if (audio_extn_passthru_is_enabled() &&
3981 audio_extn_passthru_is_passthrough_stream(out)) {
3982 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303983 }
3984 }
3985
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003986 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003987 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303988 if (!a2dp_combo) {
3989 check_a2dp_restore_l(adev, out, false);
3990 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003991 struct listnode dev;
3992 list_init(&dev);
3993 assign_devices(&dev, &out->device_list);
3994 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3995 reassign_device_list(&out->device_list,
3996 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003997 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003998 reassign_device_list(&out->device_list,
3999 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304000 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004001 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304002 }
4003 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304004 select_devices(adev, out->usecase);
4005 if (is_a2dp_out_device_type(&out->device_list) &&
4006 !adev->a2dp_started) {
4007 if (is_speaker_active || is_speaker_safe_active) {
4008 struct listnode dev;
4009 list_init(&dev);
4010 assign_devices(&dev, &out->device_list);
4011 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4012 reassign_device_list(&out->device_list,
4013 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4014 else
4015 reassign_device_list(&out->device_list,
4016 AUDIO_DEVICE_OUT_SPEAKER, "");
4017 select_devices(adev, out->usecase);
4018 assign_devices(&out->device_list, &dev);
4019 } else {
4020 ret = -EINVAL;
4021 goto error_open;
4022 }
4023 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304024 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004025
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004026 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4027 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004028 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004029 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004030
Derek Chenea197282019-01-07 17:35:01 -08004031 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4032 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004033
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004034 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4035 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004036
4037 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004038 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004039 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4040 ALOGE("%s: pcm stream not ready", __func__);
4041 goto error_open;
4042 }
4043 ret = pcm_start(out->pcm);
4044 if (ret < 0) {
4045 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4046 goto error_open;
4047 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004048 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004049 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004050 unsigned int flags = PCM_OUT;
4051 unsigned int pcm_open_retry_count = 0;
4052 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4053 flags |= PCM_MMAP | PCM_NOIRQ;
4054 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004055 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004056 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004057 } else
4058 flags |= PCM_MONOTONIC;
4059
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004060 if ((adev->vr_audio_mode_enabled) &&
4061 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4062 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4063 "PCM_Dev %d Topology", out->pcm_device_id);
4064 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4065 if (!ctl) {
4066 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4067 __func__, mixer_ctl_name);
4068 } else {
4069 //if success use ULLPP
4070 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4071 __func__, mixer_ctl_name, out->pcm_device_id);
4072 //There is a still a possibility that some sessions
4073 // that request for FAST|RAW when 3D audio is active
4074 //can go through ULLPP. Ideally we expects apps to
4075 //listen to audio focus and stop concurrent playback
4076 //Also, we will look for mode flag (voice_in_communication)
4077 //before enabling the realtime flag.
4078 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4079 }
4080 }
4081
Surendar Karka91fa3682018-07-02 18:12:12 +05304082 if (out->realtime)
4083 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4084 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4085
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004086 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4087 flags, pcm_open_retry_count,
4088 &(out->config));
4089 if (out->pcm == NULL) {
4090 ret = -EIO;
4091 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004092 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004093
4094 if (is_haptic_usecase) {
4095 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4096 adev->haptic_pcm_device_id,
4097 flags, pcm_open_retry_count,
4098 &(adev->haptics_config));
4099 // failure to open haptics pcm shouldnt stop audio,
4100 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004101
4102 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4103 ALOGD("%s: enable haptic audio synchronization", __func__);
4104 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4105 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004106 }
4107
Surendar Karka91fa3682018-07-02 18:12:12 +05304108 if (!out->realtime)
4109 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304110 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004111
Zhou Song2b8f28f2017-09-11 10:51:38 +08004112 // apply volume for voip playback after path is set up
4113 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4114 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304115 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4116 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304117 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4118 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004119 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4120 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304121 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004122 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004123 /*
4124 * set custom channel map if:
4125 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4126 * 2. custom channel map has been set by client
4127 * else default channel map of FC/FR/FL can always be set to DSP
4128 */
4129 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4130 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4131 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004132 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4133 adev->dsp_bit_width_enforce_mode,
4134 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004136 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004137 out->compr = compress_open(adev->snd_card,
4138 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004139 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004140 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304141 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304142 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4143 adev->card_status = CARD_STATUS_OFFLINE;
4144 out->card_status = CARD_STATUS_OFFLINE;
4145 ret = -EIO;
4146 goto error_open;
4147 }
4148
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004150 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151 compress_close(out->compr);
4152 out->compr = NULL;
4153 ret = -EIO;
4154 goto error_open;
4155 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304156 /* compress_open sends params of the track, so reset the flag here */
4157 out->is_compr_metadata_avail = false;
4158
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004159 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004160 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004161
Fred Oh3f43e742015-03-04 18:42:34 -08004162 /* Since small bufs uses blocking writes, a write will be blocked
4163 for the default max poll time (20s) in the event of an SSR.
4164 Reduce the poll time to observe and deal with SSR faster.
4165 */
Ashish Jain5106d362016-05-11 19:23:33 +05304166 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004167 compress_set_max_poll_wait(out->compr, 1000);
4168 }
4169
Manish Dewangan69426c82017-01-30 17:35:36 +05304170 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304171 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304172
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004173 audio_extn_dts_create_state_notifier_node(out->usecase);
4174 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4175 popcount(out->channel_mask),
4176 out->playback_started);
4177
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004178#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304179 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004180 audio_extn_dolby_send_ddp_endp_params(adev);
4181#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304182 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4183 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004184 if (adev->visualizer_start_output != NULL)
4185 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4186 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304187 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004188 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004189 }
Derek Chenf13dd492018-11-13 14:53:51 -08004190
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004191 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004192 /* Update cached volume from media to offload/direct stream */
4193 struct listnode *node = NULL;
4194 list_for_each(node, &adev->active_outputs_list) {
4195 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4196 streams_output_ctxt_t,
4197 list);
4198 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4199 out->volume_l = out_ctxt->output->volume_l;
4200 out->volume_r = out_ctxt->output->volume_r;
4201 }
4202 }
4203 out_set_compr_volume(&out->stream,
4204 out->volume_l, out->volume_r);
4205 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004207
4208 if (ret == 0) {
4209 register_out_stream(out);
4210 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004211 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4212 ALOGE("%s: pcm stream not ready", __func__);
4213 goto error_open;
4214 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004215 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004216 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004217 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004218 if (ret < 0)
4219 goto error_open;
4220 }
4221 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004222 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304223 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304224 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004225
vivek mehtad15d2bf2019-05-17 13:35:10 -07004226 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4227 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4228 audio_low_latency_hint_start();
4229 }
4230
Manish Dewangan21a850a2017-08-14 12:03:55 +05304231 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004232 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004233 if (ret < 0)
4234 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4235 }
4236
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004237 // consider a scenario where on pause lower layers are tear down.
4238 // so on resume, swap mixer control need to be sent only when
4239 // backend is active, hence rather than sending from enable device
4240 // sending it from start of streamtream
4241
4242 platform_set_swap_channels(adev, true);
4243
Haynes Mathew George380745d2017-10-04 15:27:45 -07004244 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304245 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004246 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004247error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004248 if (adev->haptic_pcm) {
4249 pcm_close(adev->haptic_pcm);
4250 adev->haptic_pcm = NULL;
4251 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004252 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304253 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004255error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304256 /*
4257 * sleep 50ms to allow sufficient time for kernel
4258 * drivers to recover incases like SSR.
4259 */
4260 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004261error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004262 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304263 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265}
4266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267static int check_input_parameters(uint32_t sample_rate,
4268 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004269 int channel_count,
4270 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004272 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304274 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4275 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4276 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004277 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004278 !audio_extn_compr_cap_format_supported(format) &&
4279 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004280 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004281
Aalique Grahame22e49102018-12-18 14:23:57 -08004282 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4283 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4284 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4285 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4286 return -EINVAL;
4287 }
4288
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004289 switch (channel_count) {
4290 case 1:
4291 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304292 case 3:
4293 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004294 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004295 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304296 case 10:
4297 case 12:
4298 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004299 break;
4300 default:
4301 ret = -EINVAL;
4302 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303
4304 switch (sample_rate) {
4305 case 8000:
4306 case 11025:
4307 case 12000:
4308 case 16000:
4309 case 22050:
4310 case 24000:
4311 case 32000:
4312 case 44100:
4313 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004314 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304315 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004316 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304317 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 break;
4319 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004320 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 }
4322
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324}
4325
Naresh Tanniru04f71882018-06-26 17:46:22 +05304326
4327/** Add a value in a list if not already present.
4328 * @return true if value was successfully inserted or already present,
4329 * false if the list is full and does not contain the value.
4330 */
4331static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4332 for (size_t i = 0; i < list_length; i++) {
4333 if (list[i] == value) return true; // value is already present
4334 if (list[i] == 0) { // no values in this slot
4335 list[i] = value;
4336 return true; // value inserted
4337 }
4338 }
4339 return false; // could not insert value
4340}
4341
4342/** Add channel_mask in supported_channel_masks if not already present.
4343 * @return true if channel_mask was successfully inserted or already present,
4344 * false if supported_channel_masks is full and does not contain channel_mask.
4345 */
4346static void register_channel_mask(audio_channel_mask_t channel_mask,
4347 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4348 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4349 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4350}
4351
4352/** Add format in supported_formats if not already present.
4353 * @return true if format was successfully inserted or already present,
4354 * false if supported_formats is full and does not contain format.
4355 */
4356static void register_format(audio_format_t format,
4357 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4358 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4359 "%s: stream can not declare supporting its format %x", __func__, format);
4360}
4361/** Add sample_rate in supported_sample_rates if not already present.
4362 * @return true if sample_rate was successfully inserted or already present,
4363 * false if supported_sample_rates is full and does not contain sample_rate.
4364 */
4365static void register_sample_rate(uint32_t sample_rate,
4366 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4367 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4368 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4369}
4370
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004371static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4372{
4373 uint32_t high = num1, low = num2, temp = 0;
4374
4375 if (!num1 || !num2)
4376 return 0;
4377
4378 if (num1 < num2) {
4379 high = num2;
4380 low = num1;
4381 }
4382
4383 while (low != 0) {
4384 temp = low;
4385 low = high % low;
4386 high = temp;
4387 }
4388 return (num1 * num2)/high;
4389}
4390
4391static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4392{
4393 uint32_t remainder = 0;
4394
4395 if (!multiplier)
4396 return num;
4397
4398 remainder = num % multiplier;
4399 if (remainder)
4400 num += (multiplier - remainder);
4401
4402 return num;
4403}
4404
Aalique Grahame22e49102018-12-18 14:23:57 -08004405static size_t get_stream_buffer_size(size_t duration_ms,
4406 uint32_t sample_rate,
4407 audio_format_t format,
4408 int channel_count,
4409 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410{
4411 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004412 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413
Aalique Grahame22e49102018-12-18 14:23:57 -08004414 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004415 if (is_low_latency)
4416 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304417
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004418 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004419 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420
Ralf Herzbd08d632018-09-28 15:50:49 +02004421 /* make sure the size is multiple of 32 bytes and additionally multiple of
4422 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004423 * At 48 kHz mono 16-bit PCM:
4424 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4425 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004426 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004427 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004428 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004429
4430 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431}
4432
Aalique Grahame22e49102018-12-18 14:23:57 -08004433static size_t get_input_buffer_size(uint32_t sample_rate,
4434 audio_format_t format,
4435 int channel_count,
4436 bool is_low_latency)
4437{
4438 /* Don't know if USB HIFI in this context so use true to be conservative */
4439 if (check_input_parameters(sample_rate, format, channel_count,
4440 true /*is_usb_hifi */) != 0)
4441 return 0;
4442
4443 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4444 sample_rate,
4445 format,
4446 channel_count,
4447 is_low_latency);
4448}
4449
Derek Chenf6318be2017-06-12 17:16:24 -04004450size_t get_output_period_size(uint32_t sample_rate,
4451 audio_format_t format,
4452 int channel_count,
4453 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304454{
4455 size_t size = 0;
4456 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4457
4458 if ((duration == 0) || (sample_rate == 0) ||
4459 (bytes_per_sample == 0) || (channel_count == 0)) {
4460 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4461 bytes_per_sample, channel_count);
4462 return -EINVAL;
4463 }
4464
4465 size = (sample_rate *
4466 duration *
4467 bytes_per_sample *
4468 channel_count) / 1000;
4469 /*
4470 * To have same PCM samples for all channels, the buffer size requires to
4471 * be multiple of (number of channels * bytes per sample)
4472 * For writes to succeed, the buffer must be written at address which is multiple of 32
4473 */
4474 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4475
4476 return (size/(channel_count * bytes_per_sample));
4477}
4478
Zhou Song48453a02018-01-10 17:50:59 +08004479static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304480{
4481 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004482 uint64_t written_frames = 0;
4483 uint64_t kernel_frames = 0;
4484 uint64_t dsp_frames = 0;
4485 uint64_t signed_frames = 0;
4486 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304487
4488 /* This adjustment accounts for buffering after app processor.
4489 * It is based on estimated DSP latency per use case, rather than exact.
4490 */
George Gao9ba8a142020-07-23 14:30:03 -07004491 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004492 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304493
Zhou Song48453a02018-01-10 17:50:59 +08004494 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004495 written_frames = out->written /
4496 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4497
Ashish Jain5106d362016-05-11 19:23:33 +05304498 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4499 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4500 * hence only estimate.
4501 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004502 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4503 kernel_frames = kernel_buffer_size /
4504 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304505
Weiyin Jiang4813da12020-05-28 00:37:28 +08004506 if (written_frames >= (kernel_frames + dsp_frames))
4507 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304508
Zhou Song48453a02018-01-10 17:50:59 +08004509 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304510 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004511 if (timestamp != NULL )
4512 *timestamp = out->writeAt;
4513 } else if (timestamp != NULL) {
4514 clock_gettime(CLOCK_MONOTONIC, timestamp);
4515 }
4516 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304517
Weiyin Jiang4813da12020-05-28 00:37:28 +08004518 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4519 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304520
4521 return actual_frames_rendered;
4522}
4523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4525{
4526 struct stream_out *out = (struct stream_out *)stream;
4527
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004528 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529}
4530
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004531static int out_set_sample_rate(struct audio_stream *stream __unused,
4532 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533{
4534 return -ENOSYS;
4535}
4536
4537static size_t out_get_buffer_size(const struct audio_stream *stream)
4538{
4539 struct stream_out *out = (struct stream_out *)stream;
4540
Varun Balaraje49253e2017-07-06 19:48:56 +05304541 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304542 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304543 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304544 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4545 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4546 else
4547 return out->compr_config.fragment_size;
4548 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004549 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304550 else if (is_offload_usecase(out->usecase) &&
4551 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304552 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004553
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004554 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004555 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556}
4557
4558static uint32_t out_get_channels(const struct audio_stream *stream)
4559{
4560 struct stream_out *out = (struct stream_out *)stream;
4561
4562 return out->channel_mask;
4563}
4564
4565static audio_format_t out_get_format(const struct audio_stream *stream)
4566{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004567 struct stream_out *out = (struct stream_out *)stream;
4568
4569 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570}
4571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004572static int out_set_format(struct audio_stream *stream __unused,
4573 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574{
4575 return -ENOSYS;
4576}
4577
4578static int out_standby(struct audio_stream *stream)
4579{
4580 struct stream_out *out = (struct stream_out *)stream;
4581 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004582 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004583
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304584 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4585 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004587 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004589 if (adev->adm_deregister_stream)
4590 adev->adm_deregister_stream(adev->adm_data, out->handle);
4591
Weiyin Jiang280ea742020-09-08 20:28:22 +08004592 if (is_offload_usecase(out->usecase)) {
4593 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004594 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004595 pthread_mutex_unlock(&out->latch_lock);
4596 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004597
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004598 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004600 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4601 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304602 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004603 pthread_mutex_unlock(&adev->lock);
4604 pthread_mutex_unlock(&out->lock);
4605 ALOGD("VOIP output entered standby");
4606 return 0;
4607 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004608 if (out->pcm) {
4609 pcm_close(out->pcm);
4610 out->pcm = NULL;
4611 }
Meng Wanga09da002020-04-20 12:56:04 +08004612 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4613 if (adev->haptic_pcm) {
4614 pcm_close(adev->haptic_pcm);
4615 adev->haptic_pcm = NULL;
4616 }
4617
4618 if (adev->haptic_buffer != NULL) {
4619 free(adev->haptic_buffer);
4620 adev->haptic_buffer = NULL;
4621 adev->haptic_buffer_size = 0;
4622 }
4623 adev->haptic_pcm_device_id = 0;
4624 }
4625
Haynes Mathew George16081042017-05-31 17:16:49 -07004626 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4627 do_stop = out->playback_started;
4628 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004629
4630 if (out->mmap_shared_memory_fd >= 0) {
4631 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4632 __func__, out->mmap_shared_memory_fd);
4633 close(out->mmap_shared_memory_fd);
4634 out->mmap_shared_memory_fd = -1;
4635 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004636 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004637 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004638 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304639 out->send_next_track_params = false;
4640 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004641 out->gapless_mdata.encoder_delay = 0;
4642 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004643 if (out->compr != NULL) {
4644 compress_close(out->compr);
4645 out->compr = NULL;
4646 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004647 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004648 if (do_stop) {
4649 stop_output_stream(out);
4650 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304651 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004652 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004653 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 }
4655 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004656 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 return 0;
4658}
4659
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304660static int out_on_error(struct audio_stream *stream)
4661{
4662 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004663 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304664
4665 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004666 // always send CMD_ERROR for offload streams, this
4667 // is needed e.g. when SSR happens within compress_open
4668 // since the stream is active, offload_callback_thread is also active.
4669 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08004670 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004671 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004672 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004673 }
4674 pthread_mutex_unlock(&out->lock);
4675
4676 status = out_standby(&out->stream.common);
4677
4678 lock_output_stream(out);
4679 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004680 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304681 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304682
4683 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4684 ALOGD("Setting previous card status if offline");
4685 out->prev_card_status_offline = true;
4686 }
4687
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304688 pthread_mutex_unlock(&out->lock);
4689
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004690 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304691}
4692
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304693/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004694 * standby implementation without locks, assumes that the callee already
4695 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304696 */
4697int out_standby_l(struct audio_stream *stream)
4698{
4699 struct stream_out *out = (struct stream_out *)stream;
4700 struct audio_device *adev = out->dev;
4701
4702 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4703 stream, out->usecase, use_case_table[out->usecase]);
4704
4705 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004706 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304707 if (adev->adm_deregister_stream)
4708 adev->adm_deregister_stream(adev->adm_data, out->handle);
4709
Weiyin Jiang280ea742020-09-08 20:28:22 +08004710 if (is_offload_usecase(out->usecase)) {
4711 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304712 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004713 pthread_mutex_unlock(&out->latch_lock);
4714 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304715
4716 out->standby = true;
4717 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4718 voice_extn_compress_voip_close_output_stream(stream);
4719 out->started = 0;
4720 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004721 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304722 return 0;
4723 } else if (!is_offload_usecase(out->usecase)) {
4724 if (out->pcm) {
4725 pcm_close(out->pcm);
4726 out->pcm = NULL;
4727 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004728 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4729 if (adev->haptic_pcm) {
4730 pcm_close(adev->haptic_pcm);
4731 adev->haptic_pcm = NULL;
4732 }
4733
4734 if (adev->haptic_buffer != NULL) {
4735 free(adev->haptic_buffer);
4736 adev->haptic_buffer = NULL;
4737 adev->haptic_buffer_size = 0;
4738 }
4739 adev->haptic_pcm_device_id = 0;
4740 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304741 } else {
4742 ALOGD("copl(%p):standby", out);
4743 out->send_next_track_params = false;
4744 out->is_compr_metadata_avail = false;
4745 out->gapless_mdata.encoder_delay = 0;
4746 out->gapless_mdata.encoder_padding = 0;
4747 if (out->compr != NULL) {
4748 compress_close(out->compr);
4749 out->compr = NULL;
4750 }
4751 }
4752 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004753 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304754 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004755 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304756 return 0;
4757}
4758
Aalique Grahame22e49102018-12-18 14:23:57 -08004759static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760{
Aalique Grahame22e49102018-12-18 14:23:57 -08004761 struct stream_out *out = (struct stream_out *)stream;
4762
4763 // We try to get the lock for consistency,
4764 // but it isn't necessary for these variables.
4765 // If we're not in standby, we may be blocked on a write.
4766 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4767 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4768 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4769
Andy Hunga1f48fa2019-07-01 18:14:53 -07004770 char buffer[256]; // for statistics formatting
4771 if (!is_offload_usecase(out->usecase)) {
4772 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4773 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4774 }
4775
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004776 if (out->start_latency_ms.n > 0) {
4777 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4778 dprintf(fd, " Start latency ms: %s\n", buffer);
4779 }
4780
Aalique Grahame22e49102018-12-18 14:23:57 -08004781 if (locked) {
4782 pthread_mutex_unlock(&out->lock);
4783 }
4784
4785 // dump error info
4786 (void)error_log_dump(
4787 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789 return 0;
4790}
4791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004792static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4793{
4794 int ret = 0;
4795 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004796
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004797 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004798 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004799 return -EINVAL;
4800 }
4801
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304802 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004803
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004804 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4805 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304806 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004807 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4809 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304810 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004811 }
4812
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004813 ALOGV("%s new encoder delay %u and padding %u", __func__,
4814 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4815
4816 return 0;
4817}
4818
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004819static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4820{
4821 return out == adev->primary_output || out == adev->voice_tx_output;
4822}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004823
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304824// note: this call is safe only if the stream_cb is
4825// removed first in close_output_stream (as is done now).
4826static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4827{
4828 if (!stream || !parms)
4829 return;
4830
4831 struct stream_out *out = (struct stream_out *)stream;
4832 struct audio_device *adev = out->dev;
4833
4834 card_status_t status;
4835 int card;
4836 if (parse_snd_card_status(parms, &card, &status) < 0)
4837 return;
4838
4839 pthread_mutex_lock(&adev->lock);
4840 bool valid_cb = (card == adev->snd_card);
4841 pthread_mutex_unlock(&adev->lock);
4842
4843 if (!valid_cb)
4844 return;
4845
4846 lock_output_stream(out);
4847 if (out->card_status != status)
4848 out->card_status = status;
4849 pthread_mutex_unlock(&out->lock);
4850
4851 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4852 use_case_table[out->usecase],
4853 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4854
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304855 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304856 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304857 if (voice_is_call_state_active(adev) &&
4858 out == adev->primary_output) {
4859 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4860 pthread_mutex_lock(&adev->lock);
4861 voice_stop_call(adev);
4862 adev->mode = AUDIO_MODE_NORMAL;
4863 pthread_mutex_unlock(&adev->lock);
4864 }
4865 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304866 return;
4867}
4868
Kevin Rocardfce19002017-08-07 19:21:36 -07004869static int get_alive_usb_card(struct str_parms* parms) {
4870 int card;
4871 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4872 !audio_extn_usb_alive(card)) {
4873 return card;
4874 }
4875 return -ENODEV;
4876}
4877
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004879 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880{
4881 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004882 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004883 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004884 bool bypass_a2dp = false;
4885 bool reconfig = false;
4886 unsigned long service_interval = 0;
4887
4888 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004889 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4890
4891 list_init(&new_devices);
4892 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004893
4894 lock_output_stream(out);
4895 pthread_mutex_lock(&adev->lock);
4896
4897 /*
4898 * When HDMI cable is unplugged the music playback is paused and
4899 * the policy manager sends routing=0. But the audioflinger continues
4900 * to write data until standby time (3sec). As the HDMI core is
4901 * turned off, the write gets blocked.
4902 * Avoid this by routing audio to speaker until standby.
4903 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004904 if (is_single_device_type_equal(&out->device_list,
4905 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004906 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004907 !audio_extn_passthru_is_passthrough_stream(out) &&
4908 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004909 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004910 }
4911 /*
4912 * When A2DP is disconnected the
4913 * music playback is paused and the policy manager sends routing=0
4914 * But the audioflinger continues to write data until standby time
4915 * (3sec). As BT is turned off, the write gets blocked.
4916 * Avoid this by routing audio to speaker until standby.
4917 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004918 if (is_a2dp_out_device_type(&out->device_list) &&
4919 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004920 !audio_extn_a2dp_source_is_ready() &&
4921 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004922 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004923 }
4924 /*
4925 * When USB headset is disconnected the music platback paused
4926 * and the policy manager send routing=0. But if the USB is connected
4927 * back before the standby time, AFE is not closed and opened
4928 * when USB is connected back. So routing to speker will guarantee
4929 * AFE reconfiguration and AFE will be opend once USB is connected again
4930 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004931 if (is_usb_out_device_type(&out->device_list) &&
4932 list_empty(&new_devices) &&
4933 !audio_extn_usb_connected(NULL)) {
4934 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4935 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004936 /* To avoid a2dp to sco overlapping / BT device improper state
4937 * check with BT lib about a2dp streaming support before routing
4938 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004939 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004940 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004941 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4942 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004943 //combo usecase just by pass a2dp
4944 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4945 bypass_a2dp = true;
4946 } else {
4947 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4948 /* update device to a2dp and don't route as BT returned error
4949 * However it is still possible a2dp routing called because
4950 * of current active device disconnection (like wired headset)
4951 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004952 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004953 pthread_mutex_unlock(&adev->lock);
4954 pthread_mutex_unlock(&out->lock);
4955 goto error;
4956 }
4957 }
4958 }
4959
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004960 // Workaround: If routing to an non existing usb device, fail gracefully
4961 // The routing request will otherwise block during 10 second
4962 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004963 if (is_usb_out_device_type(&new_devices)) {
4964 struct str_parms *parms =
4965 str_parms_create_str(get_usb_device_address(&new_devices));
4966 if (!parms)
4967 goto error;
4968 if ((card = get_alive_usb_card(parms)) >= 0) {
4969 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4970 pthread_mutex_unlock(&adev->lock);
4971 pthread_mutex_unlock(&out->lock);
4972 str_parms_destroy(parms);
4973 ret = -ENOSYS;
4974 goto error;
4975 }
4976 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004977 }
4978
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004979 // Workaround: If routing to an non existing hdmi device, fail gracefully
4980 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4981 (platform_get_edid_info_v2(adev->platform,
4982 out->extconn.cs.controller,
4983 out->extconn.cs.stream) != 0)) {
4984 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4985 pthread_mutex_unlock(&adev->lock);
4986 pthread_mutex_unlock(&out->lock);
4987 ret = -ENOSYS;
4988 goto error;
4989 }
4990
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004991 /*
4992 * select_devices() call below switches all the usecases on the same
4993 * backend to the new device. Refer to check_usecases_codec_backend() in
4994 * the select_devices(). But how do we undo this?
4995 *
4996 * For example, music playback is active on headset (deep-buffer usecase)
4997 * and if we go to ringtones and select a ringtone, low-latency usecase
4998 * will be started on headset+speaker. As we can't enable headset+speaker
4999 * and headset devices at the same time, select_devices() switches the music
5000 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5001 * So when the ringtone playback is completed, how do we undo the same?
5002 *
5003 * We are relying on the out_set_parameters() call on deep-buffer output,
5004 * once the ringtone playback is ended.
5005 * NOTE: We should not check if the current devices are same as new devices.
5006 * Because select_devices() must be called to switch back the music
5007 * playback to headset.
5008 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005009 if (!list_empty(&new_devices)) {
5010 bool same_dev = compare_devices(&out->device_list, &new_devices);
5011 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005012
5013 if (output_drives_call(adev, out)) {
5014 if (!voice_is_call_state_active(adev)) {
5015 if (adev->mode == AUDIO_MODE_IN_CALL) {
5016 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 ret = voice_start_call(adev);
5018 }
5019 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005020 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005021 adev->current_call_output = out;
5022 voice_update_devices_for_all_voice_usecases(adev);
5023 }
5024 }
5025
Mingshu Pang971ff702020-09-09 15:28:22 +08005026 if (is_usb_out_device_type(&out->device_list)) {
5027 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5028 audio_extn_usb_set_service_interval(true /*playback*/,
5029 service_interval,
5030 &reconfig);
5031 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5032 }
5033
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005034 if (!out->standby) {
5035 if (!same_dev) {
5036 ALOGV("update routing change");
5037 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5038 adev->perf_lock_opts,
5039 adev->perf_lock_opts_size);
5040 if (adev->adm_on_routing_change)
5041 adev->adm_on_routing_change(adev->adm_data,
5042 out->handle);
5043 }
5044 if (!bypass_a2dp) {
5045 select_devices(adev, out->usecase);
5046 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005047 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5048 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005050 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005051 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005052 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005053 }
5054
5055 if (!same_dev) {
5056 // on device switch force swap, lower functions will make sure
5057 // to check if swap is allowed or not.
5058 platform_set_swap_channels(adev, true);
5059 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5060 }
Zhou Songd01e7a22020-09-23 22:49:01 +08005061 if (is_offload_usecase(out->usecase) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005062 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005063 pthread_mutex_lock(&out->latch_lock);
5064 if (out->a2dp_compress_mute) {
5065 out->a2dp_compress_mute = false;
5066 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5067 }
5068 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005069 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5070 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5071 }
5072 }
5073 }
5074
5075 pthread_mutex_unlock(&adev->lock);
5076 pthread_mutex_unlock(&out->lock);
5077
5078 /*handles device and call state changes*/
5079 audio_extn_extspk_update(adev->extspk);
5080
5081error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005082 ALOGV("%s: exit: code(%d)", __func__, ret);
5083 return ret;
5084}
5085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5087{
5088 struct stream_out *out = (struct stream_out *)stream;
5089 struct audio_device *adev = out->dev;
5090 struct str_parms *parms;
5091 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005092 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005093 int ext_controller = -1;
5094 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095
sangwoobc677242013-08-08 16:53:43 +09005096 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005097 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305099 if (!parms)
5100 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005101
5102 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5103 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005104 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005105 out->extconn.cs.controller = ext_controller;
5106 out->extconn.cs.stream = ext_stream;
5107 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5108 use_case_table[out->usecase], out->extconn.cs.controller,
5109 out->extconn.cs.stream);
5110 }
5111
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005112 if (out == adev->primary_output) {
5113 pthread_mutex_lock(&adev->lock);
5114 audio_extn_set_parameters(adev, parms);
5115 pthread_mutex_unlock(&adev->lock);
5116 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005117 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005118 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005119 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005120
5121 audio_extn_dts_create_state_notifier_node(out->usecase);
5122 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5123 popcount(out->channel_mask),
5124 out->playback_started);
5125
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005126 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005127 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005128
Surendar Karkaf51b5842018-04-26 11:28:38 +05305129 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5130 sizeof(value));
5131 if (err >= 0) {
5132 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5133 audio_extn_send_dual_mono_mixing_coefficients(out);
5134 }
5135
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305136 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5137 if (err >= 0) {
5138 strlcpy(out->profile, value, sizeof(out->profile));
5139 ALOGV("updating stream profile with value '%s'", out->profile);
5140 lock_output_stream(out);
5141 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5142 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005143 &out->device_list, out->flags,
5144 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305145 out->sample_rate, out->bit_width,
5146 out->channel_mask, out->profile,
5147 &out->app_type_cfg);
5148 pthread_mutex_unlock(&out->lock);
5149 }
5150
Alexy Joseph98988832017-01-13 14:56:59 -08005151 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005152 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5153 // and vendor.audio.hal.output.suspend.supported is set to true
5154 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005155 //check suspend parameter only for low latency and if the property
5156 //is enabled
5157 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5158 ALOGI("%s: got suspend_playback %s", __func__, value);
5159 lock_output_stream(out);
5160 if (!strncmp(value, "false", 5)) {
5161 //suspend_playback=false is supposed to set QOS value back to 75%
5162 //the mixer control sent with value Enable will achieve that
5163 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5164 } else if (!strncmp (value, "true", 4)) {
5165 //suspend_playback=true is supposed to remove QOS value
5166 //resetting the mixer control will set the default value
5167 //for the mixer control which is Disable and this removes the QOS vote
5168 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5169 } else {
5170 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5171 " got %s", __func__, value);
5172 ret = -1;
5173 }
5174
5175 if (ret != 0) {
5176 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5177 __func__, out->pm_qos_mixer_path, ret);
5178 }
5179
5180 pthread_mutex_unlock(&out->lock);
5181 }
5182 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005183
Alexy Joseph98988832017-01-13 14:56:59 -08005184 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305186error:
Eric Laurent994a6932013-07-17 11:51:42 -07005187 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005188 return ret;
5189}
5190
Paul McLeana50b7332018-12-17 08:24:21 -07005191static int in_set_microphone_direction(const struct audio_stream_in *stream,
5192 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005193 struct stream_in *in = (struct stream_in *)stream;
5194
5195 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5196
5197 in->direction = dir;
5198
5199 if (in->standby)
5200 return 0;
5201
5202 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005203}
5204
5205static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005206 struct stream_in *in = (struct stream_in *)stream;
5207
5208 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5209
5210 if (zoom > 1.0 || zoom < -1.0)
5211 return -EINVAL;
5212
5213 in->zoom = zoom;
5214
5215 if (in->standby)
5216 return 0;
5217
5218 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005219}
5220
5221
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005222static bool stream_get_parameter_channels(struct str_parms *query,
5223 struct str_parms *reply,
5224 audio_channel_mask_t *supported_channel_masks) {
5225 int ret = -1;
5226 char value[512];
5227 bool first = true;
5228 size_t i, j;
5229
5230 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5231 ret = 0;
5232 value[0] = '\0';
5233 i = 0;
5234 while (supported_channel_masks[i] != 0) {
5235 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5236 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5237 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305238 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005239
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305240 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005241 first = false;
5242 break;
5243 }
5244 }
5245 i++;
5246 }
5247 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5248 }
5249 return ret == 0;
5250}
5251
5252static bool stream_get_parameter_formats(struct str_parms *query,
5253 struct str_parms *reply,
5254 audio_format_t *supported_formats) {
5255 int ret = -1;
5256 char value[256];
5257 size_t i, j;
5258 bool first = true;
5259
5260 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5261 ret = 0;
5262 value[0] = '\0';
5263 i = 0;
5264 while (supported_formats[i] != 0) {
5265 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5266 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5267 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305268 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005269 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305270 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005271 first = false;
5272 break;
5273 }
5274 }
5275 i++;
5276 }
5277 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5278 }
5279 return ret == 0;
5280}
5281
5282static bool stream_get_parameter_rates(struct str_parms *query,
5283 struct str_parms *reply,
5284 uint32_t *supported_sample_rates) {
5285
5286 int i;
5287 char value[256];
5288 int ret = -1;
5289 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5290 ret = 0;
5291 value[0] = '\0';
5292 i=0;
5293 int cursor = 0;
5294 while (supported_sample_rates[i]) {
5295 int avail = sizeof(value) - cursor;
5296 ret = snprintf(value + cursor, avail, "%s%d",
5297 cursor > 0 ? "|" : "",
5298 supported_sample_rates[i]);
5299 if (ret < 0 || ret >= avail) {
5300 // if cursor is at the last element of the array
5301 // overwrite with \0 is duplicate work as
5302 // snprintf already put a \0 in place.
5303 // else
5304 // we had space to write the '|' at value[cursor]
5305 // (which will be overwritten) or no space to fill
5306 // the first element (=> cursor == 0)
5307 value[cursor] = '\0';
5308 break;
5309 }
5310 cursor += ret;
5311 ++i;
5312 }
5313 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5314 value);
5315 }
5316 return ret >= 0;
5317}
5318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5320{
5321 struct stream_out *out = (struct stream_out *)stream;
5322 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005323 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324 char value[256];
5325 struct str_parms *reply = str_parms_create();
5326 size_t i, j;
5327 int ret;
5328 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005329
5330 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005331 if (reply) {
5332 str_parms_destroy(reply);
5333 }
5334 if (query) {
5335 str_parms_destroy(query);
5336 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005337 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5338 return NULL;
5339 }
5340
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005341 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005342 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5343 if (ret >= 0) {
5344 value[0] = '\0';
5345 i = 0;
5346 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005347 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5348 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005350 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005352 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353 first = false;
5354 break;
5355 }
5356 }
5357 i++;
5358 }
5359 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5360 str = str_parms_to_str(reply);
5361 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005362 voice_extn_out_get_parameters(out, query, reply);
5363 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005364 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005365
Alexy Joseph62142aa2015-11-16 15:10:34 -08005366
5367 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5368 if (ret >= 0) {
5369 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305370 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5371 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005372 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305373 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005374 } else {
5375 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305376 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005377 }
5378 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005379 if (str)
5380 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005381 str = str_parms_to_str(reply);
5382 }
5383
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005384 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5385 if (ret >= 0) {
5386 value[0] = '\0';
5387 i = 0;
5388 first = true;
5389 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005390 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5391 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005392 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005393 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005394 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005395 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005396 first = false;
5397 break;
5398 }
5399 }
5400 i++;
5401 }
5402 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005403 if (str)
5404 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005405 str = str_parms_to_str(reply);
5406 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005407
5408 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5409 if (ret >= 0) {
5410 value[0] = '\0';
5411 i = 0;
5412 first = true;
5413 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005414 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5415 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005416 if (!first) {
5417 strlcat(value, "|", sizeof(value));
5418 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005419 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005420 first = false;
5421 break;
5422 }
5423 }
5424 i++;
5425 }
5426 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5427 if (str)
5428 free(str);
5429 str = str_parms_to_str(reply);
5430 }
5431
Alexy Joseph98988832017-01-13 14:56:59 -08005432 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5433 //only low latency track supports suspend_resume
5434 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005435 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005436 if (str)
5437 free(str);
5438 str = str_parms_to_str(reply);
5439 }
5440
5441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442 str_parms_destroy(query);
5443 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005444 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005445 return str;
5446}
5447
5448static uint32_t out_get_latency(const struct audio_stream_out *stream)
5449{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005450 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005452 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453
Alexy Josephaa54c872014-12-03 02:46:47 -08005454 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305455 lock_output_stream(out);
5456 latency = audio_extn_utils_compress_get_dsp_latency(out);
5457 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005458 } else if ((out->realtime) ||
5459 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005460 // since the buffer won't be filled up faster than realtime,
5461 // return a smaller number
5462 if (out->config.rate)
5463 period_ms = (out->af_period_multiplier * out->config.period_size *
5464 1000) / (out->config.rate);
5465 else
5466 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005467 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005468 } else {
5469 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005470 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005471 }
5472
Zhou Songd2537a02020-06-11 22:04:46 +08005473 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005474 latency += audio_extn_a2dp_get_encoder_latency();
5475
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305476 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005477 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478}
5479
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305480static float AmpToDb(float amplification)
5481{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305482 float db = DSD_VOLUME_MIN_DB;
5483 if (amplification > 0) {
5484 db = 20 * log10(amplification);
5485 if(db < DSD_VOLUME_MIN_DB)
5486 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305487 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305488 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305489}
5490
Arun Mirpuri5d170872019-03-26 13:21:31 -07005491static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5492 float right)
5493{
5494 struct stream_out *out = (struct stream_out *)stream;
5495 long volume = 0;
5496 char mixer_ctl_name[128] = "";
5497 struct audio_device *adev = out->dev;
5498 struct mixer_ctl *ctl = NULL;
5499 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5500 PCM_PLAYBACK);
5501
5502 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5503 "Playback %d Volume", pcm_device_id);
5504 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5505 if (!ctl) {
5506 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5507 __func__, mixer_ctl_name);
5508 return -EINVAL;
5509 }
5510 if (left != right)
5511 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5512 __func__, left, right);
5513 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5514 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5515 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5516 __func__, mixer_ctl_name, volume);
5517 return -EINVAL;
5518 }
5519 return 0;
5520}
5521
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305522static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5523 float right)
5524{
5525 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305526 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305527 char mixer_ctl_name[128];
5528 struct audio_device *adev = out->dev;
5529 struct mixer_ctl *ctl;
5530 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5531 PCM_PLAYBACK);
5532
5533 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5534 "Compress Playback %d Volume", pcm_device_id);
5535 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5536 if (!ctl) {
5537 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5538 __func__, mixer_ctl_name);
5539 return -EINVAL;
5540 }
5541 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5542 __func__, mixer_ctl_name, left, right);
5543 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5544 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5545 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5546
5547 return 0;
5548}
5549
Zhou Song2b8f28f2017-09-11 10:51:38 +08005550static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5551 float right)
5552{
5553 struct stream_out *out = (struct stream_out *)stream;
5554 char mixer_ctl_name[] = "App Type Gain";
5555 struct audio_device *adev = out->dev;
5556 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305557 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005558
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005559 if (!is_valid_volume(left, right)) {
5560 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5561 __func__, left, right);
5562 return -EINVAL;
5563 }
5564
Zhou Song2b8f28f2017-09-11 10:51:38 +08005565 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5566 if (!ctl) {
5567 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5568 __func__, mixer_ctl_name);
5569 return -EINVAL;
5570 }
5571
5572 set_values[0] = 0; //0: Rx Session 1:Tx Session
5573 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305574 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5575 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005576
5577 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5578 return 0;
5579}
5580
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305581static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5582 float right)
5583{
5584 struct stream_out *out = (struct stream_out *)stream;
5585 /* Volume control for pcm playback */
5586 if (left != right) {
5587 return -EINVAL;
5588 } else {
5589 char mixer_ctl_name[128];
5590 struct audio_device *adev = out->dev;
5591 struct mixer_ctl *ctl;
5592 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5593 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5594 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5595 if (!ctl) {
5596 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5597 return -EINVAL;
5598 }
5599
5600 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5601 int ret = mixer_ctl_set_value(ctl, 0, volume);
5602 if (ret < 0) {
5603 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5604 return -EINVAL;
5605 }
5606
5607 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5608
5609 return 0;
5610 }
5611}
5612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613static int out_set_volume(struct audio_stream_out *stream, float left,
5614 float right)
5615{
Eric Laurenta9024de2013-04-04 09:19:12 -07005616 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005617 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305618 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005619
Arun Mirpuri5d170872019-03-26 13:21:31 -07005620 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005621 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5622 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiang280ea742020-09-08 20:28:22 +08005623 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005624 out->muted = (left == 0.0f);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005625 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005626 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005627 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305628 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005629 /*
5630 * Set mute or umute on HDMI passthrough stream.
5631 * Only take left channel into account.
5632 * Mute is 0 and unmute 1
5633 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305634 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305635 } else if (out->format == AUDIO_FORMAT_DSD){
5636 char mixer_ctl_name[128] = "DSD Volume";
5637 struct audio_device *adev = out->dev;
5638 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5639
5640 if (!ctl) {
5641 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5642 __func__, mixer_ctl_name);
5643 return -EINVAL;
5644 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305645 volume[0] = (long)(AmpToDb(left));
5646 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305647 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5648 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005649 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005650 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005651 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5652 struct listnode *node = NULL;
5653 list_for_each(node, &adev->active_outputs_list) {
5654 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5655 streams_output_ctxt_t,
5656 list);
5657 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5658 out->volume_l = out_ctxt->output->volume_l;
5659 out->volume_r = out_ctxt->output->volume_r;
5660 }
5661 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005662 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005663 if (!out->a2dp_compress_mute) {
5664 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5665 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005666 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005667 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005668 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005669 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005670 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305671 if (!out->a2dp_compress_mute)
5672 ret = out_set_compr_volume(stream, left, right);
5673 out->volume_l = left;
5674 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005675 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305676 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005677 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005678 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005679 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5680 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5681 if (!out->standby) {
5682 audio_extn_utils_send_app_type_gain(out->dev,
5683 out->app_type_cfg.app_type,
5684 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005685 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005686 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005687 out->volume_l = left;
5688 out->volume_r = right;
5689 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005690 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5691 ALOGV("%s: MMAP set volume called", __func__);
5692 if (!out->standby)
5693 ret = out_set_mmap_volume(stream, left, right);
5694 out->volume_l = left;
5695 out->volume_r = right;
5696 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305697 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305698 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5699 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305700 /* Volume control for pcm playback */
5701 if (!out->standby)
5702 ret = out_set_pcm_volume(stream, left, right);
5703 else
5704 out->apply_volume = true;
5705
5706 out->volume_l = left;
5707 out->volume_r = right;
5708 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005709 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5710 ALOGV("%s: bus device set volume called", __func__);
5711 if (!out->standby)
5712 ret = out_set_pcm_volume(stream, left, right);
5713 out->volume_l = left;
5714 out->volume_r = right;
5715 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005716 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005718 return -ENOSYS;
5719}
5720
Zhou Songc9672822017-08-16 16:01:39 +08005721static void update_frames_written(struct stream_out *out, size_t bytes)
5722{
5723 size_t bpf = 0;
5724
5725 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5726 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5727 bpf = 1;
5728 else if (!is_offload_usecase(out->usecase))
5729 bpf = audio_bytes_per_sample(out->format) *
5730 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005731
5732 pthread_mutex_lock(&out->position_query_lock);
5733 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005734 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005735 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5736 }
5737 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005738}
5739
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005740int split_and_write_audio_haptic_data(struct stream_out *out,
5741 const void *buffer, size_t bytes_to_write)
5742{
5743 struct audio_device *adev = out->dev;
5744
5745 int ret = 0;
5746 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5747 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5748 size_t frame_size = channel_count * bytes_per_sample;
5749 size_t frame_count = bytes_to_write / frame_size;
5750
5751 bool force_haptic_path =
5752 property_get_bool("vendor.audio.test_haptic", false);
5753
5754 // extract Haptics data from Audio buffer
5755 bool alloc_haptic_buffer = false;
5756 int haptic_channel_count = adev->haptics_config.channels;
5757 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5758 size_t audio_frame_size = frame_size - haptic_frame_size;
5759 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5760
5761 if (adev->haptic_buffer == NULL) {
5762 alloc_haptic_buffer = true;
5763 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5764 free(adev->haptic_buffer);
5765 adev->haptic_buffer_size = 0;
5766 alloc_haptic_buffer = true;
5767 }
5768
5769 if (alloc_haptic_buffer) {
5770 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005771 if(adev->haptic_buffer == NULL) {
5772 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5773 return -ENOMEM;
5774 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005775 adev->haptic_buffer_size = total_haptic_buffer_size;
5776 }
5777
5778 size_t src_index = 0, aud_index = 0, hap_index = 0;
5779 uint8_t *audio_buffer = (uint8_t *)buffer;
5780 uint8_t *haptic_buffer = adev->haptic_buffer;
5781
5782 // This is required for testing only. This works for stereo data only.
5783 // One channel is fed to audio stream and other to haptic stream for testing.
5784 if (force_haptic_path)
5785 audio_frame_size = haptic_frame_size = bytes_per_sample;
5786
5787 for (size_t i = 0; i < frame_count; i++) {
5788 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5789 audio_frame_size);
5790 aud_index += audio_frame_size;
5791 src_index += audio_frame_size;
5792
5793 if (adev->haptic_pcm)
5794 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5795 haptic_frame_size);
5796 hap_index += haptic_frame_size;
5797 src_index += haptic_frame_size;
5798
5799 // This is required for testing only.
5800 // Discard haptic channel data.
5801 if (force_haptic_path)
5802 src_index += haptic_frame_size;
5803 }
5804
5805 // write to audio pipeline
5806 ret = pcm_write(out->pcm, (void *)audio_buffer,
5807 frame_count * audio_frame_size);
5808
5809 // write to haptics pipeline
5810 if (adev->haptic_pcm)
5811 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5812 frame_count * haptic_frame_size);
5813
5814 return ret;
5815}
5816
Aalique Grahame22e49102018-12-18 14:23:57 -08005817#ifdef NO_AUDIO_OUT
5818static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5819 const void *buffer __unused, size_t bytes)
5820{
5821 struct stream_out *out = (struct stream_out *)stream;
5822
5823 /* No Output device supported other than BT for playback.
5824 * Sleep for the amount of buffer duration
5825 */
5826 lock_output_stream(out);
5827 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5828 (const struct audio_stream_out *)&out->stream) /
5829 out_get_sample_rate(&out->stream.common));
5830 pthread_mutex_unlock(&out->lock);
5831 return bytes;
5832}
5833#endif
5834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005835static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5836 size_t bytes)
5837{
5838 struct stream_out *out = (struct stream_out *)stream;
5839 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005840 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305841 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005842 const size_t frame_size = audio_stream_out_frame_size(stream);
5843 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305844 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005845 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846
Haynes Mathew George380745d2017-10-04 15:27:45 -07005847 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005848 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305849
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305850 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005851
Dhananjay Kumarac341582017-02-23 23:42:25 +05305852 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305853 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305854 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5855 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005856 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305857 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305858 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305859 ALOGD(" %s: sound card is not active/SSR state", __func__);
5860 ret= -EIO;
5861 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305862 }
5863 }
5864
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305865 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305866 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305867 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305868 goto exit;
5869 }
5870
Haynes Mathew George16081042017-05-31 17:16:49 -07005871 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5872 ret = -EINVAL;
5873 goto exit;
5874 }
5875
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005876 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305877 !out->is_iec61937_info_available) {
5878
5879 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5880 out->is_iec61937_info_available = true;
5881 } else if (audio_extn_passthru_is_enabled()) {
5882 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305883 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305884
5885 if((out->format == AUDIO_FORMAT_DTS) ||
5886 (out->format == AUDIO_FORMAT_DTS_HD)) {
5887 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5888 buffer, bytes);
5889 if (ret) {
5890 if (ret != -ENOSYS) {
5891 out->is_iec61937_info_available = false;
5892 ALOGD("iec61937 transmission info not yet updated retry");
5893 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305894 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305895 /* if stream has started and after that there is
5896 * stream config change (iec transmission config)
5897 * then trigger select_device to update backend configuration.
5898 */
5899 out->stream_config_changed = true;
5900 pthread_mutex_lock(&adev->lock);
5901 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305902 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005903 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305904 ret = -EINVAL;
5905 goto exit;
5906 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305907 pthread_mutex_unlock(&adev->lock);
5908 out->stream_config_changed = false;
5909 out->is_iec61937_info_available = true;
5910 }
5911 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305912
Meng Wang4c32fb42020-01-16 17:57:11 +08005913#ifdef AUDIO_GKI_ENABLED
5914 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5915 compr_passthr = out->compr_config.codec->reserved[0];
5916#else
5917 compr_passthr = out->compr_config.codec->compr_passthr;
5918#endif
5919
Garmond Leung317cbf12017-09-13 16:20:50 -07005920 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005921 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305922 (out->is_iec61937_info_available == true)) {
5923 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5924 ret = -EINVAL;
5925 goto exit;
5926 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305927 }
5928 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305929
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005930 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005931 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005932 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5933 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005934 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305935 ret = -EIO;
5936 goto exit;
5937 }
5938 }
5939 }
5940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005941 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005942 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005943 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5944
Eric Laurent150dbfe2013-02-27 14:31:02 -08005945 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005946 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5947 ret = voice_extn_compress_voip_start_output_stream(out);
5948 else
5949 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005950 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005951 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005952 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005953 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005954 goto exit;
5955 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305956 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005957 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005958
5959 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005960 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005961 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305962 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005963 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005964 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305965
5966 if ((out->is_iec61937_info_available == true) &&
5967 (audio_extn_passthru_is_passthrough_stream(out))&&
5968 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5969 ret = -EINVAL;
5970 goto exit;
5971 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305972 if (out->set_dual_mono)
5973 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005974
5975 // log startup time in ms.
5976 simple_stats_log(
5977 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005979
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005980 if (adev->is_channel_status_set == false &&
5981 compare_device_type(&out->device_list,
5982 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005983 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305984 adev->is_channel_status_set = true;
5985 }
5986
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305987 if ((adev->use_old_pspd_mix_ctrl == true) &&
5988 (out->pspd_coeff_sent == false)) {
5989 /*
5990 * Need to resend pspd coefficients after stream started for
5991 * older kernel version as it does not save the coefficients
5992 * and also stream has to be started for coeff to apply.
5993 */
5994 usecase = get_usecase_from_list(adev, out->usecase);
5995 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305996 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305997 out->pspd_coeff_sent = true;
5998 }
5999 }
6000
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006001 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006002 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006003 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006004 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006005 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6006 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306007 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6008 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006009 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306010 out->send_next_track_params = false;
6011 out->is_compr_metadata_avail = false;
6012 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006013 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306014 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306015 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006016
Ashish Jain83a6cc22016-06-28 14:34:17 +05306017 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306018 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306019 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306020 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006021 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306022 return -EINVAL;
6023 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306024 audio_format_t dst_format = out->hal_op_format;
6025 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306026
Dieter Luecking5d57def2018-09-07 14:23:37 +02006027 /* prevent division-by-zero */
6028 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6029 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6030 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6031 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306032 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006033 ATRACE_END();
6034 return -EINVAL;
6035 }
6036
Ashish Jainf1eaa582016-05-23 20:54:24 +05306037 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6038 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6039
Ashish Jain83a6cc22016-06-28 14:34:17 +05306040 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306041 dst_format,
6042 buffer,
6043 src_format,
6044 frames);
6045
Ashish Jain83a6cc22016-06-28 14:34:17 +05306046 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306047 bytes_to_write);
6048
6049 /*Convert written bytes in audio flinger format*/
6050 if (ret > 0)
6051 ret = ((ret * format_to_bitwidth_table[out->format]) /
6052 format_to_bitwidth_table[dst_format]);
6053 }
6054 } else
6055 ret = compress_write(out->compr, buffer, bytes);
6056
Zhou Songc9672822017-08-16 16:01:39 +08006057 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6058 update_frames_written(out, bytes);
6059
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306060 if (ret < 0)
6061 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006062 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306063 /*msg to cb thread only if non blocking write is enabled*/
6064 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306065 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006066 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306067 } else if (-ENETRESET == ret) {
6068 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306069 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306070 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306071 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006072 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306073 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006074 }
Ashish Jain5106d362016-05-11 19:23:33 +05306075
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306076 /* Call compr start only when non-zero bytes of data is there to be rendered */
6077 if (!out->playback_started && ret > 0) {
6078 int status = compress_start(out->compr);
6079 if (status < 0) {
6080 ret = status;
6081 ALOGE("%s: compr start failed with err %d", __func__, errno);
6082 goto exit;
6083 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006084 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006085 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006086 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006087 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006088 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006089
6090 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6091 popcount(out->channel_mask),
6092 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006093 }
6094 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006095 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006096 return ret;
6097 } else {
6098 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006099 size_t bytes_to_write = bytes;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006100 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006101 if (out->muted)
6102 memset((void *)buffer, 0, bytes);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006103 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006104 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6105 __func__, frames, frame_size, bytes_to_write);
6106
Aalique Grahame22e49102018-12-18 14:23:57 -08006107 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006108 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6109 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6110 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006111 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6112 int16_t *src = (int16_t *)buffer;
6113 int16_t *dst = (int16_t *)buffer;
6114
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006115 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006116 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006117 "out_write called for %s use case with wrong properties",
6118 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006119
6120 /*
6121 * FIXME: this can be removed once audio flinger mixer supports
6122 * mono output
6123 */
6124
6125 /*
6126 * Code below goes over each frame in the buffer and adds both
6127 * L and R samples and then divides by 2 to convert to mono
6128 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006129 if (channel_count == 2) {
6130 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6131 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6132 }
6133 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006134 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006135 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006136
6137 // Note: since out_get_presentation_position() is called alternating with out_write()
6138 // by AudioFlinger, we can check underruns using the prior timestamp read.
6139 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6140 if (out->last_fifo_valid) {
6141 // compute drain to see if there is an underrun.
6142 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306143 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6144 int64_t frames_by_time =
6145 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6146 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006147 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6148
6149 if (underrun > 0) {
6150 simple_stats_log(&out->fifo_underruns, underrun);
6151
6152 ALOGW("%s: underrun(%lld) "
6153 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6154 __func__,
6155 (long long)out->fifo_underruns.n,
6156 (long long)frames_by_time,
6157 (long long)out->last_fifo_frames_remaining);
6158 }
6159 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6160 }
6161
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306162 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006163
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006164 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006165
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006166 if (out->config.rate)
6167 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6168 out->config.rate;
6169
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006170 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006171 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6172
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006173 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006174 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006175 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306176 out->convert_buffer != NULL) {
6177
6178 memcpy_by_audio_format(out->convert_buffer,
6179 out->hal_op_format,
6180 buffer,
6181 out->hal_ip_format,
6182 out->config.period_size * out->config.channels);
6183
6184 ret = pcm_write(out->pcm, out->convert_buffer,
6185 (out->config.period_size *
6186 out->config.channels *
6187 format_to_bitwidth_table[out->hal_op_format]));
6188 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306189 /*
6190 * To avoid underrun in DSP when the application is not pumping
6191 * data at required rate, check for the no. of bytes and ignore
6192 * pcm_write if it is less than actual buffer size.
6193 * It is a work around to a change in compress VOIP driver.
6194 */
6195 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6196 bytes < (out->config.period_size * out->config.channels *
6197 audio_bytes_per_sample(out->format))) {
6198 size_t voip_buf_size =
6199 out->config.period_size * out->config.channels *
6200 audio_bytes_per_sample(out->format);
6201 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6202 __func__, bytes, voip_buf_size);
6203 usleep(((uint64_t)voip_buf_size - bytes) *
6204 1000000 / audio_stream_out_frame_size(stream) /
6205 out_get_sample_rate(&out->stream.common));
6206 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006207 } else {
6208 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6209 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6210 else
6211 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6212 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306213 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006214
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006215 release_out_focus(out);
6216
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306217 if (ret < 0)
6218 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006219 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306220 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006221 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006222 }
6223
6224exit:
Zhou Songc9672822017-08-16 16:01:39 +08006225 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306226 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306227 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306228 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006229 pthread_mutex_unlock(&out->lock);
6230
6231 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006232 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006233 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306234 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306235 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306236 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306237 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306238 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306239 out->standby = true;
6240 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306241 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006242 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6243 /* prevent division-by-zero */
6244 uint32_t stream_size = audio_stream_out_frame_size(stream);
6245 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006246
Dieter Luecking5d57def2018-09-07 14:23:37 +02006247 if ((stream_size == 0) || (srate == 0)) {
6248 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6249 ATRACE_END();
6250 return -EINVAL;
6251 }
6252 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6253 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006254 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306255 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006256 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006257 return ret;
6258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006259 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006260 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261 return bytes;
6262}
6263
6264static int out_get_render_position(const struct audio_stream_out *stream,
6265 uint32_t *dsp_frames)
6266{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006267 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006268
6269 if (dsp_frames == NULL)
6270 return -EINVAL;
6271
6272 *dsp_frames = 0;
6273 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006274 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306275
6276 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6277 * this operation and adev_close_output_stream(where out gets reset).
6278 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306279 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006280 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306281 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006282 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306283 return 0;
6284 }
6285
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006286 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306287 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306288 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006289 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306290 if (ret < 0)
6291 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006292 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306293 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006294 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306295 if (-ENETRESET == ret) {
6296 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306297 out->card_status = CARD_STATUS_OFFLINE;
6298 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306299 } else if(ret < 0) {
6300 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306301 ret = -EINVAL;
6302 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306303 /*
6304 * Handle corner case where compress session is closed during SSR
6305 * and timestamp is queried
6306 */
6307 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306308 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306309 } else if (out->prev_card_status_offline) {
6310 ALOGE("ERROR: previously sound card was offline,return error");
6311 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306312 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306313 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006314 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306315 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306316 pthread_mutex_unlock(&out->lock);
6317 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006318 } else if (audio_is_linear_pcm(out->format)) {
6319 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006320 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006321 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006322 } else
6323 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006324}
6325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006326static int out_add_audio_effect(const struct audio_stream *stream __unused,
6327 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006328{
6329 return 0;
6330}
6331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006332static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6333 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006334{
6335 return 0;
6336}
6337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006338static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6339 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006340{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306341 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342}
6343
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006344static int out_get_presentation_position(const struct audio_stream_out *stream,
6345 uint64_t *frames, struct timespec *timestamp)
6346{
6347 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306348 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006349 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006350
Ashish Jain5106d362016-05-11 19:23:33 +05306351 /* below piece of code is not guarded against any lock because audioFliner serializes
6352 * this operation and adev_close_output_stream( where out gets reset).
6353 */
6354 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306355 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006356 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306357 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6358 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6359 return 0;
6360 }
6361
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006362 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006363
Ashish Jain5106d362016-05-11 19:23:33 +05306364 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6365 ret = compress_get_tstamp(out->compr, &dsp_frames,
6366 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006367 // Adjustment accounts for A2dp encoder latency with offload usecases
6368 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006369 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006370 unsigned long offset =
6371 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6372 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6373 }
Ashish Jain5106d362016-05-11 19:23:33 +05306374 ALOGVV("%s rendered frames %ld sample_rate %d",
6375 __func__, dsp_frames, out->sample_rate);
6376 *frames = dsp_frames;
6377 if (ret < 0)
6378 ret = -errno;
6379 if (-ENETRESET == ret) {
6380 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306381 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306382 ret = -EINVAL;
6383 } else
6384 ret = 0;
6385 /* this is the best we can do */
6386 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006387 } else {
6388 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006389 unsigned int avail;
6390 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006391 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006392 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006393
Andy Hunga1f48fa2019-07-01 18:14:53 -07006394 if (out->kernel_buffer_size > avail) {
6395 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6396 } else {
6397 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6398 __func__, avail, out->kernel_buffer_size);
6399 avail = out->kernel_buffer_size;
6400 frames_temp = out->last_fifo_frames_remaining = 0;
6401 }
6402 out->last_fifo_valid = true;
6403 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6404
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006405 if (out->written >= frames_temp)
6406 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006407
Andy Hunga1f48fa2019-07-01 18:14:53 -07006408 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6409 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6410
Weiyin Jiangd4633762018-03-16 12:05:03 +08006411 // This adjustment accounts for buffering after app processor.
6412 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006413 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006414 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006415 if (signed_frames >= frames_temp)
6416 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006417
Weiyin Jiangd4633762018-03-16 12:05:03 +08006418 // Adjustment accounts for A2dp encoder latency with non offload usecases
6419 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006420 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006421 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6422 if (signed_frames >= frames_temp)
6423 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006424 }
6425
6426 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006427 *frames = signed_frames;
6428 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006429 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006430 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6431 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006432 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306433 *frames = out->written;
6434 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306435 if (is_offload_usecase(out->usecase))
6436 ret = -EINVAL;
6437 else
6438 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006439 }
6440 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006441 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006442 return ret;
6443}
6444
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006445static int out_set_callback(struct audio_stream_out *stream,
6446 stream_callback_t callback, void *cookie)
6447{
6448 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006449 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006450
6451 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006452 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006453 out->client_callback = callback;
6454 out->client_cookie = cookie;
6455 if (out->adsp_hdlr_stream_handle) {
6456 ret = audio_extn_adsp_hdlr_stream_set_callback(
6457 out->adsp_hdlr_stream_handle,
6458 callback,
6459 cookie);
6460 if (ret)
6461 ALOGW("%s:adsp hdlr callback registration failed %d",
6462 __func__, ret);
6463 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006464 pthread_mutex_unlock(&out->lock);
6465 return 0;
6466}
6467
6468static int out_pause(struct audio_stream_out* stream)
6469{
6470 struct stream_out *out = (struct stream_out *)stream;
6471 int status = -ENOSYS;
6472 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006473 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006474 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306475 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006476 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006477 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006478 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306479 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306480 status = compress_pause(out->compr);
6481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006482 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006483
Mingming Yin21854652016-04-13 11:54:02 -07006484 if (audio_extn_passthru_is_active()) {
6485 ALOGV("offload use case, pause passthru");
6486 audio_extn_passthru_on_pause(out);
6487 }
6488
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306489 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006490 audio_extn_dts_notify_playback_state(out->usecase, 0,
6491 out->sample_rate, popcount(out->channel_mask),
6492 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006493 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006494 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006495 pthread_mutex_unlock(&out->lock);
6496 }
6497 return status;
6498}
6499
6500static int out_resume(struct audio_stream_out* stream)
6501{
6502 struct stream_out *out = (struct stream_out *)stream;
6503 int status = -ENOSYS;
6504 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006505 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006506 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306507 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006508 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006509 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006510 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306511 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306512 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006513 }
6514 if (!status) {
6515 out->offload_state = OFFLOAD_STATE_PLAYING;
6516 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306517 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006518 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6519 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006520 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006521 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006522 pthread_mutex_unlock(&out->lock);
6523 }
6524 return status;
6525}
6526
6527static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6528{
6529 struct stream_out *out = (struct stream_out *)stream;
6530 int status = -ENOSYS;
6531 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006532 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006533 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006534 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6535 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6536 else
6537 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6538 pthread_mutex_unlock(&out->lock);
6539 }
6540 return status;
6541}
6542
6543static int out_flush(struct audio_stream_out* stream)
6544{
6545 struct stream_out *out = (struct stream_out *)stream;
6546 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006547 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006548 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006549 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006550 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006551 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6552 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006553 } else {
6554 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6555 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006556 out->written = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006557 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006558 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006559 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006560 return 0;
6561 }
6562 return -ENOSYS;
6563}
6564
Haynes Mathew George16081042017-05-31 17:16:49 -07006565static int out_stop(const struct audio_stream_out* stream)
6566{
6567 struct stream_out *out = (struct stream_out *)stream;
6568 struct audio_device *adev = out->dev;
6569 int ret = -ENOSYS;
6570
6571 ALOGV("%s", __func__);
6572 pthread_mutex_lock(&adev->lock);
6573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6574 out->playback_started && out->pcm != NULL) {
6575 pcm_stop(out->pcm);
6576 ret = stop_output_stream(out);
6577 out->playback_started = false;
6578 }
6579 pthread_mutex_unlock(&adev->lock);
6580 return ret;
6581}
6582
6583static int out_start(const struct audio_stream_out* stream)
6584{
6585 struct stream_out *out = (struct stream_out *)stream;
6586 struct audio_device *adev = out->dev;
6587 int ret = -ENOSYS;
6588
6589 ALOGV("%s", __func__);
6590 pthread_mutex_lock(&adev->lock);
6591 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6592 !out->playback_started && out->pcm != NULL) {
6593 ret = start_output_stream(out);
6594 if (ret == 0) {
6595 out->playback_started = true;
6596 }
6597 }
6598 pthread_mutex_unlock(&adev->lock);
6599 return ret;
6600}
6601
6602/*
6603 * Modify config->period_count based on min_size_frames
6604 */
6605static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6606{
6607 int periodCountRequested = (min_size_frames + config->period_size - 1)
6608 / config->period_size;
6609 int periodCount = MMAP_PERIOD_COUNT_MIN;
6610
6611 ALOGV("%s original config.period_size = %d config.period_count = %d",
6612 __func__, config->period_size, config->period_count);
6613
6614 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6615 periodCount *= 2;
6616 }
6617 config->period_count = periodCount;
6618
6619 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6620}
6621
Phil Burkfe17efd2019-03-25 10:23:35 -07006622// Read offset for the positional timestamp from a persistent vendor property.
6623// This is to workaround apparent inaccuracies in the timing information that
6624// is used by the AAudio timing model. The inaccuracies can cause glitches.
6625static int64_t get_mmap_out_time_offset() {
6626 const int32_t kDefaultOffsetMicros = 0;
6627 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006628 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006629 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6630 return mmap_time_offset_micros * (int64_t)1000;
6631}
6632
Haynes Mathew George16081042017-05-31 17:16:49 -07006633static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6634 int32_t min_size_frames,
6635 struct audio_mmap_buffer_info *info)
6636{
6637 struct stream_out *out = (struct stream_out *)stream;
6638 struct audio_device *adev = out->dev;
6639 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006640 unsigned int offset1 = 0;
6641 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006642 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006643 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006644 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006645
Arun Mirpuri5d170872019-03-26 13:21:31 -07006646 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306647 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006648 pthread_mutex_lock(&adev->lock);
6649
Sharad Sanglec6f32552018-05-04 16:15:38 +05306650 if (CARD_STATUS_OFFLINE == out->card_status ||
6651 CARD_STATUS_OFFLINE == adev->card_status) {
6652 ALOGW("out->card_status or adev->card_status offline, try again");
6653 ret = -EIO;
6654 goto exit;
6655 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306656 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006657 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6658 ret = -EINVAL;
6659 goto exit;
6660 }
6661 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6662 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6663 ret = -ENOSYS;
6664 goto exit;
6665 }
6666 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6667 if (out->pcm_device_id < 0) {
6668 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6669 __func__, out->pcm_device_id, out->usecase);
6670 ret = -EINVAL;
6671 goto exit;
6672 }
6673
6674 adjust_mmap_period_count(&out->config, min_size_frames);
6675
Arun Mirpuri5d170872019-03-26 13:21:31 -07006676 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006677 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6678 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6679 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306680 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306681 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6682 out->card_status = CARD_STATUS_OFFLINE;
6683 adev->card_status = CARD_STATUS_OFFLINE;
6684 ret = -EIO;
6685 goto exit;
6686 }
6687
Haynes Mathew George16081042017-05-31 17:16:49 -07006688 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6689 step = "open";
6690 ret = -ENODEV;
6691 goto exit;
6692 }
6693 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6694 if (ret < 0) {
6695 step = "begin";
6696 goto exit;
6697 }
juyuchen626833d2019-06-04 16:48:02 +08006698
6699 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006700 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006701 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006702 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006703 ret = platform_get_mmap_data_fd(adev->platform,
6704 out->pcm_device_id, 0 /*playback*/,
6705 &info->shared_memory_fd,
6706 &mmap_size);
6707 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006708 // Fall back to non exclusive mode
6709 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6710 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006711 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6712 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6713
Arun Mirpuri5d170872019-03-26 13:21:31 -07006714 if (mmap_size < buffer_size) {
6715 step = "mmap";
6716 goto exit;
6717 }
juyuchen626833d2019-06-04 16:48:02 +08006718 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006719 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006720 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006721 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006722
6723 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6724 if (ret < 0) {
6725 step = "commit";
6726 goto exit;
6727 }
6728
Phil Burkfe17efd2019-03-25 10:23:35 -07006729 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6730
Haynes Mathew George16081042017-05-31 17:16:49 -07006731 out->standby = false;
6732 ret = 0;
6733
Arun Mirpuri5d170872019-03-26 13:21:31 -07006734 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006735 __func__, info->shared_memory_address, info->buffer_size_frames);
6736
6737exit:
6738 if (ret != 0) {
6739 if (out->pcm == NULL) {
6740 ALOGE("%s: %s - %d", __func__, step, ret);
6741 } else {
6742 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6743 pcm_close(out->pcm);
6744 out->pcm = NULL;
6745 }
6746 }
6747 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306748 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006749 return ret;
6750}
6751
6752static int out_get_mmap_position(const struct audio_stream_out *stream,
6753 struct audio_mmap_position *position)
6754{
6755 struct stream_out *out = (struct stream_out *)stream;
6756 ALOGVV("%s", __func__);
6757 if (position == NULL) {
6758 return -EINVAL;
6759 }
6760 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006761 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006762 return -ENOSYS;
6763 }
6764 if (out->pcm == NULL) {
6765 return -ENOSYS;
6766 }
6767
6768 struct timespec ts = { 0, 0 };
6769 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6770 if (ret < 0) {
6771 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6772 return ret;
6773 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006774 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6775 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006776 return 0;
6777}
6778
6779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006780/** audio_stream_in implementation **/
6781static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6782{
6783 struct stream_in *in = (struct stream_in *)stream;
6784
6785 return in->config.rate;
6786}
6787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006788static int in_set_sample_rate(struct audio_stream *stream __unused,
6789 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006790{
6791 return -ENOSYS;
6792}
6793
6794static size_t in_get_buffer_size(const struct audio_stream *stream)
6795{
6796 struct stream_in *in = (struct stream_in *)stream;
6797
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006798 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6799 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006800 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6801 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306802 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306803 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006804
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006805 return in->config.period_size * in->af_period_multiplier *
6806 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006807}
6808
6809static uint32_t in_get_channels(const struct audio_stream *stream)
6810{
6811 struct stream_in *in = (struct stream_in *)stream;
6812
6813 return in->channel_mask;
6814}
6815
6816static audio_format_t in_get_format(const struct audio_stream *stream)
6817{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006818 struct stream_in *in = (struct stream_in *)stream;
6819
6820 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006821}
6822
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006823static int in_set_format(struct audio_stream *stream __unused,
6824 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006825{
6826 return -ENOSYS;
6827}
6828
6829static int in_standby(struct audio_stream *stream)
6830{
6831 struct stream_in *in = (struct stream_in *)stream;
6832 struct audio_device *adev = in->dev;
6833 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306834 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6835 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006836 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306837
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006838 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006839 if (!in->standby && in->is_st_session) {
6840 ALOGD("%s: sound trigger pcm stop lab", __func__);
6841 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006842 if (adev->num_va_sessions > 0)
6843 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006844 in->standby = 1;
6845 }
6846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006847 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006848 if (adev->adm_deregister_stream)
6849 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6850
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006851 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006853 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006854 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006855 voice_extn_compress_voip_close_input_stream(stream);
6856 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006857 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6858 do_stop = in->capture_started;
6859 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006860 if (in->mmap_shared_memory_fd >= 0) {
6861 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6862 __func__, in->mmap_shared_memory_fd);
6863 close(in->mmap_shared_memory_fd);
6864 in->mmap_shared_memory_fd = -1;
6865 }
Zhou Songa8895042016-07-05 17:54:22 +08006866 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306867 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306868 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006869 }
6870
Arun Mirpuri5d170872019-03-26 13:21:31 -07006871 if (in->pcm) {
6872 ATRACE_BEGIN("pcm_in_close");
6873 pcm_close(in->pcm);
6874 ATRACE_END();
6875 in->pcm = NULL;
6876 }
6877
Carter Hsu2e429db2019-05-14 18:50:52 +08006878 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006879 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006880
George Gao3018ede2019-10-23 13:23:00 -07006881 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6882 if (adev->num_va_sessions > 0)
6883 adev->num_va_sessions--;
6884 }
Quinn Malef6050362019-01-30 15:55:40 -08006885
Eric Laurent150dbfe2013-02-27 14:31:02 -08006886 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006887 }
6888 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006889 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006890 return status;
6891}
6892
Aalique Grahame22e49102018-12-18 14:23:57 -08006893static int in_dump(const struct audio_stream *stream,
6894 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006895{
Aalique Grahame22e49102018-12-18 14:23:57 -08006896 struct stream_in *in = (struct stream_in *)stream;
6897
6898 // We try to get the lock for consistency,
6899 // but it isn't necessary for these variables.
6900 // If we're not in standby, we may be blocked on a read.
6901 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6902 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6903 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6904 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6905
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006906 char buffer[256]; // for statistics formatting
6907 if (in->start_latency_ms.n > 0) {
6908 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6909 dprintf(fd, " Start latency ms: %s\n", buffer);
6910 }
6911
Aalique Grahame22e49102018-12-18 14:23:57 -08006912 if (locked) {
6913 pthread_mutex_unlock(&in->lock);
6914 }
6915
6916 // dump error info
6917 (void)error_log_dump(
6918 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006920 return 0;
6921}
6922
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306923static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6924{
6925 if (!stream || !parms)
6926 return;
6927
6928 struct stream_in *in = (struct stream_in *)stream;
6929 struct audio_device *adev = in->dev;
6930
6931 card_status_t status;
6932 int card;
6933 if (parse_snd_card_status(parms, &card, &status) < 0)
6934 return;
6935
6936 pthread_mutex_lock(&adev->lock);
6937 bool valid_cb = (card == adev->snd_card);
6938 pthread_mutex_unlock(&adev->lock);
6939
6940 if (!valid_cb)
6941 return;
6942
6943 lock_input_stream(in);
6944 if (in->card_status != status)
6945 in->card_status = status;
6946 pthread_mutex_unlock(&in->lock);
6947
6948 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6949 use_case_table[in->usecase],
6950 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6951
6952 // a better solution would be to report error back to AF and let
6953 // it put the stream to standby
6954 if (status == CARD_STATUS_OFFLINE)
6955 in_standby(&in->stream.common);
6956
6957 return;
6958}
6959
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006960int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006961 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006962 audio_source_t source)
6963{
6964 struct audio_device *adev = in->dev;
6965 int ret = 0;
6966
6967 lock_input_stream(in);
6968 pthread_mutex_lock(&adev->lock);
6969
6970 /* no audio source uses val == 0 */
6971 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6972 in->source = source;
6973 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6974 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6975 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6976 (in->config.rate == 8000 || in->config.rate == 16000 ||
6977 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6978 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6979 ret = voice_extn_compress_voip_open_input_stream(in);
6980 if (ret != 0) {
6981 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6982 __func__, ret);
6983 }
6984 }
6985 }
6986
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006987 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6988 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006989 // Workaround: If routing to an non existing usb device, fail gracefully
6990 // The routing request will otherwise block during 10 second
6991 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006992 struct str_parms *usb_addr =
6993 str_parms_create_str(get_usb_device_address(devices));
6994 if (is_usb_in_device_type(devices) && usb_addr &&
6995 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006996 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6997 ret = -ENOSYS;
6998 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006999 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007000 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007001 if (!in->standby && !in->is_st_session) {
7002 ALOGV("update input routing change");
7003 // inform adm before actual routing to prevent glitches.
7004 if (adev->adm_on_routing_change) {
7005 adev->adm_on_routing_change(adev->adm_data,
7006 in->capture_handle);
7007 ret = select_devices(adev, in->usecase);
7008 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7009 adev->adm_routing_changed = true;
7010 }
7011 }
7012 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007013 if (usb_addr)
7014 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007015 }
7016 pthread_mutex_unlock(&adev->lock);
7017 pthread_mutex_unlock(&in->lock);
7018
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007019 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007020 return ret;
7021}
7022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007023static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7024{
7025 struct stream_in *in = (struct stream_in *)stream;
7026 struct audio_device *adev = in->dev;
7027 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007028 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307029 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007030
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307031 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007032 parms = str_parms_create_str(kvpairs);
7033
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307034 if (!parms)
7035 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007036 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007037 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007038
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307039 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7040 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307041 strlcpy(in->profile, value, sizeof(in->profile));
7042 ALOGV("updating stream profile with value '%s'", in->profile);
7043 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7044 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007045 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307046 in->sample_rate, in->bit_width,
7047 in->profile, &in->app_type_cfg);
7048 }
7049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007051 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007052
7053 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307054error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307055 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007056}
7057
7058static char* in_get_parameters(const struct audio_stream *stream,
7059 const char *keys)
7060{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007061 struct stream_in *in = (struct stream_in *)stream;
7062 struct str_parms *query = str_parms_create_str(keys);
7063 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007064 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007065
7066 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007067 if (reply) {
7068 str_parms_destroy(reply);
7069 }
7070 if (query) {
7071 str_parms_destroy(query);
7072 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007073 ALOGE("in_get_parameters: failed to create query or reply");
7074 return NULL;
7075 }
7076
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007077 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007078
7079 voice_extn_in_get_parameters(in, query, reply);
7080
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007081 stream_get_parameter_channels(query, reply,
7082 &in->supported_channel_masks[0]);
7083 stream_get_parameter_formats(query, reply,
7084 &in->supported_formats[0]);
7085 stream_get_parameter_rates(query, reply,
7086 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007087 str = str_parms_to_str(reply);
7088 str_parms_destroy(query);
7089 str_parms_destroy(reply);
7090
7091 ALOGV("%s: exit: returns - %s", __func__, str);
7092 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007093}
7094
Aalique Grahame22e49102018-12-18 14:23:57 -08007095static int in_set_gain(struct audio_stream_in *stream,
7096 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007097{
Aalique Grahame22e49102018-12-18 14:23:57 -08007098 struct stream_in *in = (struct stream_in *)stream;
7099 char mixer_ctl_name[128];
7100 struct mixer_ctl *ctl;
7101 int ctl_value;
7102
7103 ALOGV("%s: gain %f", __func__, gain);
7104
7105 if (stream == NULL)
7106 return -EINVAL;
7107
7108 /* in_set_gain() only used to silence MMAP capture for now */
7109 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7110 return -ENOSYS;
7111
7112 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7113
7114 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7115 if (!ctl) {
7116 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7117 __func__, mixer_ctl_name);
7118 return -ENOSYS;
7119 }
7120
7121 if (gain < RECORD_GAIN_MIN)
7122 gain = RECORD_GAIN_MIN;
7123 else if (gain > RECORD_GAIN_MAX)
7124 gain = RECORD_GAIN_MAX;
7125 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7126
7127 mixer_ctl_set_value(ctl, 0, ctl_value);
7128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007129 return 0;
7130}
7131
7132static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7133 size_t bytes)
7134{
7135 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307136
7137 if (in == NULL) {
7138 ALOGE("%s: stream_in ptr is NULL", __func__);
7139 return -EINVAL;
7140 }
7141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307143 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307144 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007145
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007146 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307147
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007148 if (in->is_st_session) {
7149 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7150 /* Read from sound trigger HAL */
7151 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007152 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007153 if (adev->num_va_sessions < UINT_MAX)
7154 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007155 in->standby = 0;
7156 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007157 pthread_mutex_unlock(&in->lock);
7158 return bytes;
7159 }
7160
Haynes Mathew George16081042017-05-31 17:16:49 -07007161 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7162 ret = -ENOSYS;
7163 goto exit;
7164 }
7165
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007166 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7167 !in->standby && adev->adm_routing_changed) {
7168 ret = -ENOSYS;
7169 goto exit;
7170 }
7171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007172 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007173 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7174
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007175 pthread_mutex_lock(&adev->lock);
7176 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7177 ret = voice_extn_compress_voip_start_input_stream(in);
7178 else
7179 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007180 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7181 if (adev->num_va_sessions < UINT_MAX)
7182 adev->num_va_sessions++;
7183 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007184 pthread_mutex_unlock(&adev->lock);
7185 if (ret != 0) {
7186 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187 }
7188 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007189
7190 // log startup time in ms.
7191 simple_stats_log(
7192 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007194
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307195 /* Avoid read if capture_stopped is set */
7196 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7197 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7198 ret = -EINVAL;
7199 goto exit;
7200 }
7201
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007202 // what's the duration requested by the client?
7203 long ns = 0;
7204
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307205 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007206 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7207 in->config.rate;
7208
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007209 ret = request_in_focus(in, ns);
7210 if (ret != 0)
7211 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007212 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007213
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307214 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307215 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7216 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307217 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007218 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307219 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007220 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007221 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007222 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007223 } else if (audio_extn_ffv_get_stream() == in) {
7224 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307225 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007226 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307227 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7228 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7229 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7230 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307231 ret = -EINVAL;
7232 goto exit;
7233 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307234 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307235 ret = -errno;
7236 }
7237 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307238 /* bytes read is always set to bytes for non compress usecases */
7239 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007240 }
7241
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007242 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 /*
Quinn Malef6050362019-01-30 15:55:40 -08007245 * Instead of writing zeroes here, we could trust the hardware to always
7246 * provide zeroes when muted. This is also muted with voice recognition
7247 * usecases so that other clients do not have access to voice recognition
7248 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249 */
Quinn Malef6050362019-01-30 15:55:40 -08007250 if ((ret == 0 && voice_get_mic_mute(adev) &&
7251 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007252 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7253 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007254 (adev->num_va_sessions &&
7255 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7256 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7257 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007258 memset(buffer, 0, bytes);
7259
7260exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307261 frame_size = audio_stream_in_frame_size(stream);
7262 if (frame_size > 0)
7263 in->frames_read += bytes_read/frame_size;
7264
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007265 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307266 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007267 pthread_mutex_unlock(&in->lock);
7268
7269 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307270 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307271 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307272 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307273 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307274 in->standby = true;
7275 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307276 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307277 bytes_read = bytes;
7278 memset(buffer, 0, bytes);
7279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007280 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007281 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7282 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007283 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307284 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307285 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007286 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307287 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007288}
7289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007290static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291{
7292 return 0;
7293}
7294
Aalique Grahame22e49102018-12-18 14:23:57 -08007295static int in_get_capture_position(const struct audio_stream_in *stream,
7296 int64_t *frames, int64_t *time)
7297{
7298 if (stream == NULL || frames == NULL || time == NULL) {
7299 return -EINVAL;
7300 }
7301 struct stream_in *in = (struct stream_in *)stream;
7302 int ret = -ENOSYS;
7303
7304 lock_input_stream(in);
7305 // note: ST sessions do not close the alsa pcm driver synchronously
7306 // on standby. Therefore, we may return an error even though the
7307 // pcm stream is still opened.
7308 if (in->standby) {
7309 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7310 "%s stream in standby but pcm not NULL for non ST session", __func__);
7311 goto exit;
7312 }
7313 if (in->pcm) {
7314 struct timespec timestamp;
7315 unsigned int avail;
7316 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7317 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007318 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007319 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007320 ret = 0;
7321 }
7322 }
7323exit:
7324 pthread_mutex_unlock(&in->lock);
7325 return ret;
7326}
7327
Carter Hsu2e429db2019-05-14 18:50:52 +08007328static int in_update_effect_list(bool add, effect_handle_t effect,
7329 struct listnode *head)
7330{
7331 struct listnode *node;
7332 struct in_effect_list *elist = NULL;
7333 struct in_effect_list *target = NULL;
7334 int ret = 0;
7335
7336 if (!head)
7337 return ret;
7338
7339 list_for_each(node, head) {
7340 elist = node_to_item(node, struct in_effect_list, list);
7341 if (elist->handle == effect) {
7342 target = elist;
7343 break;
7344 }
7345 }
7346
7347 if (add) {
7348 if (target) {
7349 ALOGD("effect %p already exist", effect);
7350 return ret;
7351 }
7352
7353 target = (struct in_effect_list *)
7354 calloc(1, sizeof(struct in_effect_list));
7355
7356 if (!target) {
7357 ALOGE("%s:fail to allocate memory", __func__);
7358 return -ENOMEM;
7359 }
7360
7361 target->handle = effect;
7362 list_add_tail(head, &target->list);
7363 } else {
7364 if (target) {
7365 list_remove(&target->list);
7366 free(target);
7367 }
7368 }
7369
7370 return ret;
7371}
7372
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007373static int add_remove_audio_effect(const struct audio_stream *stream,
7374 effect_handle_t effect,
7375 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007376{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007377 struct stream_in *in = (struct stream_in *)stream;
7378 int status = 0;
7379 effect_descriptor_t desc;
7380
7381 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007382 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7383
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007384 if (status != 0)
7385 return status;
7386
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007387 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007388 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007389 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007390 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7391 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007392 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007393
7394 in_update_effect_list(enable, effect, &in->aec_list);
7395 enable = !list_empty(&in->aec_list);
7396 if (enable == in->enable_aec)
7397 goto exit;
7398
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007399 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007400 ALOGD("AEC enable %d", enable);
7401
Aalique Grahame22e49102018-12-18 14:23:57 -08007402 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7403 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7404 in->dev->enable_voicerx = enable;
7405 struct audio_usecase *usecase;
7406 struct listnode *node;
7407 list_for_each(node, &in->dev->usecase_list) {
7408 usecase = node_to_item(node, struct audio_usecase, list);
7409 if (usecase->type == PCM_PLAYBACK)
7410 select_devices(in->dev, usecase->id);
7411 }
7412 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007413 if (!in->standby) {
7414 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7415 select_devices(in->dev, in->usecase);
7416 }
7417
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007418 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007419 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7420
7421 in_update_effect_list(enable, effect, &in->ns_list);
7422 enable = !list_empty(&in->ns_list);
7423 if (enable == in->enable_ns)
7424 goto exit;
7425
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007426 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007427 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007428 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007429 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7430 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007431 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7432 select_devices(in->dev, in->usecase);
7433 } else
7434 select_devices(in->dev, in->usecase);
7435 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007436 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007437exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007438 pthread_mutex_unlock(&in->dev->lock);
7439 pthread_mutex_unlock(&in->lock);
7440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007441 return 0;
7442}
7443
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007444static int in_add_audio_effect(const struct audio_stream *stream,
7445 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007446{
Eric Laurent994a6932013-07-17 11:51:42 -07007447 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007448 return add_remove_audio_effect(stream, effect, true);
7449}
7450
7451static int in_remove_audio_effect(const struct audio_stream *stream,
7452 effect_handle_t effect)
7453{
Eric Laurent994a6932013-07-17 11:51:42 -07007454 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007455 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007456}
7457
Derek Chenf939fb72018-11-13 13:34:41 -08007458streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7459 audio_io_handle_t input)
7460{
7461 struct listnode *node;
7462
7463 list_for_each(node, &dev->active_inputs_list) {
7464 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7465 streams_input_ctxt_t,
7466 list);
7467 if (in_ctxt->input->capture_handle == input) {
7468 return in_ctxt;
7469 }
7470 }
7471 return NULL;
7472}
7473
7474streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7475 audio_io_handle_t output)
7476{
7477 struct listnode *node;
7478
7479 list_for_each(node, &dev->active_outputs_list) {
7480 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7481 streams_output_ctxt_t,
7482 list);
7483 if (out_ctxt->output->handle == output) {
7484 return out_ctxt;
7485 }
7486 }
7487 return NULL;
7488}
7489
Haynes Mathew George16081042017-05-31 17:16:49 -07007490static int in_stop(const struct audio_stream_in* stream)
7491{
7492 struct stream_in *in = (struct stream_in *)stream;
7493 struct audio_device *adev = in->dev;
7494
7495 int ret = -ENOSYS;
7496 ALOGV("%s", __func__);
7497 pthread_mutex_lock(&adev->lock);
7498 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7499 in->capture_started && in->pcm != NULL) {
7500 pcm_stop(in->pcm);
7501 ret = stop_input_stream(in);
7502 in->capture_started = false;
7503 }
7504 pthread_mutex_unlock(&adev->lock);
7505 return ret;
7506}
7507
7508static int in_start(const struct audio_stream_in* stream)
7509{
7510 struct stream_in *in = (struct stream_in *)stream;
7511 struct audio_device *adev = in->dev;
7512 int ret = -ENOSYS;
7513
7514 ALOGV("%s in %p", __func__, in);
7515 pthread_mutex_lock(&adev->lock);
7516 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7517 !in->capture_started && in->pcm != NULL) {
7518 if (!in->capture_started) {
7519 ret = start_input_stream(in);
7520 if (ret == 0) {
7521 in->capture_started = true;
7522 }
7523 }
7524 }
7525 pthread_mutex_unlock(&adev->lock);
7526 return ret;
7527}
7528
Phil Burke0a86d12019-02-16 22:28:11 -08007529// Read offset for the positional timestamp from a persistent vendor property.
7530// This is to workaround apparent inaccuracies in the timing information that
7531// is used by the AAudio timing model. The inaccuracies can cause glitches.
7532static int64_t in_get_mmap_time_offset() {
7533 const int32_t kDefaultOffsetMicros = 0;
7534 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007535 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007536 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7537 return mmap_time_offset_micros * (int64_t)1000;
7538}
7539
Haynes Mathew George16081042017-05-31 17:16:49 -07007540static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7541 int32_t min_size_frames,
7542 struct audio_mmap_buffer_info *info)
7543{
7544 struct stream_in *in = (struct stream_in *)stream;
7545 struct audio_device *adev = in->dev;
7546 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007547 unsigned int offset1 = 0;
7548 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007549 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007550 uint32_t mmap_size = 0;
7551 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007552
7553 pthread_mutex_lock(&adev->lock);
7554 ALOGV("%s in %p", __func__, in);
7555
Sharad Sanglec6f32552018-05-04 16:15:38 +05307556 if (CARD_STATUS_OFFLINE == in->card_status||
7557 CARD_STATUS_OFFLINE == adev->card_status) {
7558 ALOGW("in->card_status or adev->card_status offline, try again");
7559 ret = -EIO;
7560 goto exit;
7561 }
7562
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307563 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007564 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7565 ret = -EINVAL;
7566 goto exit;
7567 }
7568 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7569 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7570 ALOGV("%s in %p", __func__, in);
7571 ret = -ENOSYS;
7572 goto exit;
7573 }
7574 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7575 if (in->pcm_device_id < 0) {
7576 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7577 __func__, in->pcm_device_id, in->usecase);
7578 ret = -EINVAL;
7579 goto exit;
7580 }
7581
7582 adjust_mmap_period_count(&in->config, min_size_frames);
7583
7584 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7585 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7586 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7587 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307588 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307589 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7590 in->card_status = CARD_STATUS_OFFLINE;
7591 adev->card_status = CARD_STATUS_OFFLINE;
7592 ret = -EIO;
7593 goto exit;
7594 }
7595
Haynes Mathew George16081042017-05-31 17:16:49 -07007596 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7597 step = "open";
7598 ret = -ENODEV;
7599 goto exit;
7600 }
7601
7602 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7603 if (ret < 0) {
7604 step = "begin";
7605 goto exit;
7606 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007607
juyuchen626833d2019-06-04 16:48:02 +08007608 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007609 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7610 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7611 info->burst_size_frames = in->config.period_size;
7612 ret = platform_get_mmap_data_fd(adev->platform,
7613 in->pcm_device_id, 1 /*capture*/,
7614 &info->shared_memory_fd,
7615 &mmap_size);
7616 if (ret < 0) {
7617 // Fall back to non exclusive mode
7618 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7619 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007620 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7621 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7622
Arun Mirpuri5d170872019-03-26 13:21:31 -07007623 if (mmap_size < buffer_size) {
7624 step = "mmap";
7625 goto exit;
7626 }
juyuchen626833d2019-06-04 16:48:02 +08007627 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007628 }
7629
7630 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007631
7632 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7633 if (ret < 0) {
7634 step = "commit";
7635 goto exit;
7636 }
7637
Phil Burke0a86d12019-02-16 22:28:11 -08007638 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7639
Haynes Mathew George16081042017-05-31 17:16:49 -07007640 in->standby = false;
7641 ret = 0;
7642
7643 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7644 __func__, info->shared_memory_address, info->buffer_size_frames);
7645
7646exit:
7647 if (ret != 0) {
7648 if (in->pcm == NULL) {
7649 ALOGE("%s: %s - %d", __func__, step, ret);
7650 } else {
7651 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7652 pcm_close(in->pcm);
7653 in->pcm = NULL;
7654 }
7655 }
7656 pthread_mutex_unlock(&adev->lock);
7657 return ret;
7658}
7659
7660static int in_get_mmap_position(const struct audio_stream_in *stream,
7661 struct audio_mmap_position *position)
7662{
7663 struct stream_in *in = (struct stream_in *)stream;
7664 ALOGVV("%s", __func__);
7665 if (position == NULL) {
7666 return -EINVAL;
7667 }
7668 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7669 return -ENOSYS;
7670 }
7671 if (in->pcm == NULL) {
7672 return -ENOSYS;
7673 }
7674 struct timespec ts = { 0, 0 };
7675 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7676 if (ret < 0) {
7677 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7678 return ret;
7679 }
Phil Burke0a86d12019-02-16 22:28:11 -08007680 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7681 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007682 return 0;
7683}
7684
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307685static int in_get_active_microphones(const struct audio_stream_in *stream,
7686 struct audio_microphone_characteristic_t *mic_array,
7687 size_t *mic_count) {
7688 struct stream_in *in = (struct stream_in *)stream;
7689 struct audio_device *adev = in->dev;
7690 ALOGVV("%s", __func__);
7691
7692 lock_input_stream(in);
7693 pthread_mutex_lock(&adev->lock);
7694 int ret = platform_get_active_microphones(adev->platform,
7695 audio_channel_count_from_in_mask(in->channel_mask),
7696 in->usecase, mic_array, mic_count);
7697 pthread_mutex_unlock(&adev->lock);
7698 pthread_mutex_unlock(&in->lock);
7699
7700 return ret;
7701}
7702
7703static int adev_get_microphones(const struct audio_hw_device *dev,
7704 struct audio_microphone_characteristic_t *mic_array,
7705 size_t *mic_count) {
7706 struct audio_device *adev = (struct audio_device *)dev;
7707 ALOGVV("%s", __func__);
7708
7709 pthread_mutex_lock(&adev->lock);
7710 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7711 pthread_mutex_unlock(&adev->lock);
7712
7713 return ret;
7714}
juyuchendb308c22019-01-21 11:57:17 -07007715
7716static void in_update_sink_metadata(struct audio_stream_in *stream,
7717 const struct sink_metadata *sink_metadata) {
7718
7719 if (stream == NULL
7720 || sink_metadata == NULL
7721 || sink_metadata->tracks == NULL) {
7722 return;
7723 }
7724
7725 int error = 0;
7726 struct stream_in *in = (struct stream_in *)stream;
7727 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007728 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007729 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007730
7731 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007732
7733 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007734 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007735
7736 lock_input_stream(in);
7737 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007738 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007739
Zhou Song62ea0282020-03-22 19:53:01 +08007740 is_ha_usecase = adev->ha_proxy_enable ?
7741 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7742 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7743 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007744 && adev->voice_tx_output != NULL) {
7745 /* Use the rx device from afe-proxy record to route voice call because
7746 there is no routing if tx device is on primary hal and rx device
7747 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007748 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007749
7750 if (!voice_is_call_state_active(adev)) {
7751 if (adev->mode == AUDIO_MODE_IN_CALL) {
7752 adev->current_call_output = adev->voice_tx_output;
7753 error = voice_start_call(adev);
7754 if (error != 0)
7755 ALOGE("%s: start voice call failed %d", __func__, error);
7756 }
7757 } else {
7758 adev->current_call_output = adev->voice_tx_output;
7759 voice_update_devices_for_all_voice_usecases(adev);
7760 }
7761 }
7762
7763 pthread_mutex_unlock(&adev->lock);
7764 pthread_mutex_unlock(&in->lock);
7765}
7766
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307767int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007768 audio_io_handle_t handle,
7769 audio_devices_t devices,
7770 audio_output_flags_t flags,
7771 struct audio_config *config,
7772 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007773 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007774{
7775 struct audio_device *adev = (struct audio_device *)dev;
7776 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307777 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007778 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007779 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307780 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007781 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7782 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7783 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7784 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007785 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007786 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7787 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007788 bool force_haptic_path =
7789 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007790 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007791#ifdef AUDIO_GKI_ENABLED
7792 __s32 *generic_dec;
7793#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007794
kunleizdff872d2018-08-20 14:40:33 +08007795 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007796 is_usb_dev = false;
7797 devices = AUDIO_DEVICE_OUT_SPEAKER;
7798 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7799 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007800 if (config->format == AUDIO_FORMAT_DEFAULT)
7801 config->format = AUDIO_FORMAT_PCM_16_BIT;
7802 if (config->sample_rate == 0)
7803 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7804 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7805 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007806 }
7807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007808 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307809
Rahul Sharma99770982019-03-06 17:05:26 +05307810 pthread_mutex_lock(&adev->lock);
7811 if (out_get_stream(adev, handle) != NULL) {
7812 ALOGW("%s, output stream already opened", __func__);
7813 ret = -EEXIST;
7814 }
7815 pthread_mutex_unlock(&adev->lock);
7816 if (ret)
7817 return ret;
7818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007819 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7820
Mingming Yin3a941d42016-02-17 18:08:05 -08007821 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007822 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7823 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307824
7825
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007826 if (!out) {
7827 return -ENOMEM;
7828 }
7829
Haynes Mathew George204045b2015-02-25 20:32:03 -08007830 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007831 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007832 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007833 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007834 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007836 if (devices == AUDIO_DEVICE_NONE)
7837 devices = AUDIO_DEVICE_OUT_SPEAKER;
7838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007839 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007840 list_init(&out->device_list);
7841 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007842 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007843 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007844 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307845 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307846 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7847 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7848 else
7849 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007850 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007851 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007852 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307853 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307854 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307855 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007856 out->hal_output_suspend_supported = 0;
7857 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307858 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307859 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307860 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007861 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007862
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307863 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307864 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007865 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7866
Aalique Grahame22e49102018-12-18 14:23:57 -08007867 if (direct_dev &&
7868 (audio_is_linear_pcm(out->format) ||
7869 config->format == AUDIO_FORMAT_DEFAULT) &&
7870 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7871 audio_format_t req_format = config->format;
7872 audio_channel_mask_t req_channel_mask = config->channel_mask;
7873 uint32_t req_sample_rate = config->sample_rate;
7874
7875 pthread_mutex_lock(&adev->lock);
7876 if (is_hdmi) {
7877 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7878 ret = read_hdmi_sink_caps(out);
7879 if (config->sample_rate == 0)
7880 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7881 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7882 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7883 if (config->format == AUDIO_FORMAT_DEFAULT)
7884 config->format = AUDIO_FORMAT_PCM_16_BIT;
7885 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007886 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7887 &config->format,
7888 &out->supported_formats[0],
7889 MAX_SUPPORTED_FORMATS,
7890 &config->channel_mask,
7891 &out->supported_channel_masks[0],
7892 MAX_SUPPORTED_CHANNEL_MASKS,
7893 &config->sample_rate,
7894 &out->supported_sample_rates[0],
7895 MAX_SUPPORTED_SAMPLE_RATES);
7896 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007897 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007898
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007899 pthread_mutex_unlock(&adev->lock);
7900 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007901 if (ret == -ENOSYS) {
7902 /* ignore and go with default */
7903 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007904 }
7905 // For MMAP NO IRQ, allow conversions in ADSP
7906 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7907 goto error_open;
7908 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007909 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007910 goto error_open;
7911 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007912
7913 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7914 config->sample_rate = req_sample_rate;
7915 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7916 config->channel_mask = req_channel_mask;
7917 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7918 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007919 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007920
7921 out->sample_rate = config->sample_rate;
7922 out->channel_mask = config->channel_mask;
7923 out->format = config->format;
7924 if (is_hdmi) {
7925 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7926 out->config = pcm_config_hdmi_multi;
7927 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7928 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7929 out->config = pcm_config_mmap_playback;
7930 out->stream.start = out_start;
7931 out->stream.stop = out_stop;
7932 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7933 out->stream.get_mmap_position = out_get_mmap_position;
7934 } else {
7935 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7936 out->config = pcm_config_hifi;
7937 }
7938
7939 out->config.rate = out->sample_rate;
7940 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7941 if (is_hdmi) {
7942 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7943 audio_bytes_per_sample(out->format));
7944 }
7945 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007946 }
7947
Derek Chenf6318be2017-06-12 17:16:24 -04007948 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007949 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007950 /* extract car audio stream index */
7951 out->car_audio_stream =
7952 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7953 if (out->car_audio_stream < 0) {
7954 ALOGE("%s: invalid car audio stream %x",
7955 __func__, out->car_audio_stream);
7956 ret = -EINVAL;
7957 goto error_open;
7958 }
Derek Chen5f67a942020-02-24 23:08:13 -08007959 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007960 }
7961
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007962 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007963 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007964 if (!voice_extn_is_compress_voip_supported()) {
7965 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7966 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007967 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307968 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007969 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7970 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007971 out->volume_l = INVALID_OUT_VOLUME;
7972 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007973
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007974 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007975 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007976 uint32_t channel_count =
7977 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307978 out->config.channels = channel_count;
7979
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007980 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7981 out->sample_rate, out->format,
7982 channel_count, false);
7983 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7984 if (frame_size != 0)
7985 out->config.period_size = buffer_size / frame_size;
7986 else
7987 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007988 }
7989 } else {
7990 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7991 voice_extn_compress_voip_is_active(out->dev)) &&
7992 (voice_extn_compress_voip_is_config_supported(config))) {
7993 ret = voice_extn_compress_voip_open_output_stream(out);
7994 if (ret != 0) {
7995 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7996 __func__, ret);
7997 goto error_open;
7998 }
Sujin Panicker19027262019-09-16 18:28:06 +05307999 } else {
8000 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8001 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008002 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008003 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008004 } else if (audio_is_linear_pcm(out->format) &&
8005 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8006 out->channel_mask = config->channel_mask;
8007 out->sample_rate = config->sample_rate;
8008 out->format = config->format;
8009 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8010 // does this change?
8011 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8012 out->config.rate = config->sample_rate;
8013 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8014 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8015 audio_bytes_per_sample(config->format));
8016 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008017 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308018 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308019 pthread_mutex_lock(&adev->lock);
8020 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8021 pthread_mutex_unlock(&adev->lock);
8022
8023 // reject offload during card offline to allow
8024 // fallback to s/w paths
8025 if (offline) {
8026 ret = -ENODEV;
8027 goto error_open;
8028 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008030 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8031 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8032 ALOGE("%s: Unsupported Offload information", __func__);
8033 ret = -EINVAL;
8034 goto error_open;
8035 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008036
Atul Khare3fa6e542017-08-09 00:56:17 +05308037 if (config->offload_info.format == 0)
8038 config->offload_info.format = config->format;
8039 if (config->offload_info.sample_rate == 0)
8040 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008041
Mingming Yin90310102013-11-13 16:57:00 -08008042 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308043 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008044 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008045 ret = -EINVAL;
8046 goto error_open;
8047 }
8048
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008049 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8050 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8051 (audio_extn_passthru_is_passthrough_stream(out)) &&
8052 !((config->sample_rate == 48000) ||
8053 (config->sample_rate == 96000) ||
8054 (config->sample_rate == 192000))) {
8055 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8056 __func__, config->sample_rate, config->offload_info.format);
8057 ret = -EINVAL;
8058 goto error_open;
8059 }
8060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008061 out->compr_config.codec = (struct snd_codec *)
8062 calloc(1, sizeof(struct snd_codec));
8063
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008064 if (!out->compr_config.codec) {
8065 ret = -ENOMEM;
8066 goto error_open;
8067 }
8068
Dhananjay Kumarac341582017-02-23 23:42:25 +05308069 out->stream.pause = out_pause;
8070 out->stream.resume = out_resume;
8071 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308072 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308073 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008074 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308075 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008076 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308077 } else {
8078 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8079 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008080 }
vivek mehta446c3962015-09-14 10:57:35 -07008081
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308082 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8083 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008084#ifdef AUDIO_GKI_ENABLED
8085 /* out->compr_config.codec->reserved[1] is for flags */
8086 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8087#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308088 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008089#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308090 }
8091
vivek mehta446c3962015-09-14 10:57:35 -07008092 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008093 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008094 config->format == 0 && config->sample_rate == 0 &&
8095 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008096 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008097 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8098 } else {
8099 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8100 ret = -EEXIST;
8101 goto error_open;
8102 }
vivek mehta446c3962015-09-14 10:57:35 -07008103 }
8104
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008105 if (config->offload_info.channel_mask)
8106 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008107 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008108 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008109 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008110 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308111 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008112 ret = -EINVAL;
8113 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008114 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008115
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008116 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008117 out->sample_rate = config->offload_info.sample_rate;
8118
Mingming Yin3ee55c62014-08-04 14:23:35 -07008119 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008120
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308121 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308122 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308123 audio_extn_dolby_send_ddp_endp_params(adev);
8124 audio_extn_dolby_set_dmid(adev);
8125 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008127 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008128 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008129 out->compr_config.codec->bit_rate =
8130 config->offload_info.bit_rate;
8131 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308132 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008133 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308134 /* Update bit width only for non passthrough usecases.
8135 * For passthrough usecases, the output will always be opened @16 bit
8136 */
8137 if (!audio_extn_passthru_is_passthrough_stream(out))
8138 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308139
8140 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008141#ifdef AUDIO_GKI_ENABLED
8142 /* out->compr_config.codec->reserved[1] is for flags */
8143 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8144 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8145#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308146 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8147 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008148#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308149
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008150 /*TODO: Do we need to change it for passthrough */
8151 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008152
Manish Dewangana6fc5442015-08-24 20:30:31 +05308153 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8154 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308155 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308156 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308157 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8158 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308159
8160 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8161 AUDIO_FORMAT_PCM) {
8162
8163 /*Based on platform support, configure appropriate alsa format for corresponding
8164 *hal input format.
8165 */
8166 out->compr_config.codec->format = hal_format_to_alsa(
8167 config->offload_info.format);
8168
Ashish Jain83a6cc22016-06-28 14:34:17 +05308169 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308170 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308171 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308172
Dhananjay Kumarac341582017-02-23 23:42:25 +05308173 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308174 *hal input format and alsa format might differ based on platform support.
8175 */
8176 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308177 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308178
8179 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8180
Deeraj Soman93155a62019-09-30 19:00:37 +05308181 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8182 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8183 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8184 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8185 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308186
Ashish Jainf1eaa582016-05-23 20:54:24 +05308187 /* Check if alsa session is configured with the same format as HAL input format,
8188 * if not then derive correct fragment size needed to accomodate the
8189 * conversion of HAL input format to alsa format.
8190 */
8191 audio_extn_utils_update_direct_pcm_fragment_size(out);
8192
8193 /*if hal input and output fragment size is different this indicates HAL input format is
8194 *not same as the alsa format
8195 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308196 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308197 /*Allocate a buffer to convert input data to the alsa configured format.
8198 *size of convert buffer is equal to the size required to hold one fragment size
8199 *worth of pcm data, this is because flinger does not write more than fragment_size
8200 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308201 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8202 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308203 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8204 ret = -ENOMEM;
8205 goto error_open;
8206 }
8207 }
8208 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8209 out->compr_config.fragment_size =
8210 audio_extn_passthru_get_buffer_size(&config->offload_info);
8211 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8212 } else {
8213 out->compr_config.fragment_size =
8214 platform_get_compress_offload_buffer_size(&config->offload_info);
8215 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8216 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008217
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308218 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8219 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8220 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008221 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8222#ifdef AUDIO_GKI_ENABLED
8223 generic_dec =
8224 &(out->compr_config.codec->options.generic.reserved[1]);
8225 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8226 AUDIO_OUTPUT_BIT_WIDTH;
8227#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308228 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008229#endif
8230 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008231
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308232 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8233 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8234 }
8235
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008236 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8237 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008238
Manish Dewangan69426c82017-01-30 17:35:36 +05308239 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8240 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8241 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8242 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8243 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8244 } else {
8245 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8246 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008247
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308248 memset(&out->channel_map_param, 0,
8249 sizeof(struct audio_out_channel_map_param));
8250
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008251 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308252 out->send_next_track_params = false;
8253 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008254 out->offload_state = OFFLOAD_STATE_IDLE;
8255 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008256 out->writeAt.tv_sec = 0;
8257 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008258
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008259 audio_extn_dts_create_state_notifier_node(out->usecase);
8260
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008261 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8262 __func__, config->offload_info.version,
8263 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308264
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308265 /* Check if DSD audio format is supported in codec
8266 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308267 */
8268
8269 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308270 (!platform_check_codec_dsd_support(adev->platform) ||
8271 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308272 ret = -EINVAL;
8273 goto error_open;
8274 }
8275
Ashish Jain5106d362016-05-11 19:23:33 +05308276 /* Disable gapless if any of the following is true
8277 * passthrough playback
8278 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308279 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308280 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308281 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308282 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008283 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308284 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308285 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308286 check_and_set_gapless_mode(adev, false);
8287 } else
8288 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008289
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308290 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008291 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8292 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308293 if (config->format == AUDIO_FORMAT_DSD) {
8294 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008295#ifdef AUDIO_GKI_ENABLED
8296 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8297 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8298#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308299 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008300#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308301 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008302
8303 create_offload_callback_thread(out);
8304
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008305 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008306 switch (config->sample_rate) {
8307 case 0:
8308 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8309 break;
8310 case 8000:
8311 case 16000:
8312 case 48000:
8313 out->sample_rate = config->sample_rate;
8314 break;
8315 default:
8316 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8317 config->sample_rate);
8318 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8319 ret = -EINVAL;
8320 goto error_open;
8321 }
8322 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8323 switch (config->channel_mask) {
8324 case AUDIO_CHANNEL_NONE:
8325 case AUDIO_CHANNEL_OUT_STEREO:
8326 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8327 break;
8328 default:
8329 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8330 config->channel_mask);
8331 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8332 ret = -EINVAL;
8333 goto error_open;
8334 }
8335 switch (config->format) {
8336 case AUDIO_FORMAT_DEFAULT:
8337 case AUDIO_FORMAT_PCM_16_BIT:
8338 out->format = AUDIO_FORMAT_PCM_16_BIT;
8339 break;
8340 default:
8341 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8342 config->format);
8343 config->format = AUDIO_FORMAT_PCM_16_BIT;
8344 ret = -EINVAL;
8345 goto error_open;
8346 }
8347
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308348 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008349 if (ret != 0) {
8350 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008351 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008352 goto error_open;
8353 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008354 } else if (is_single_device_type_equal(&out->device_list,
8355 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008356 switch (config->sample_rate) {
8357 case 0:
8358 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8359 break;
8360 case 8000:
8361 case 16000:
8362 case 48000:
8363 out->sample_rate = config->sample_rate;
8364 break;
8365 default:
8366 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8367 config->sample_rate);
8368 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8369 ret = -EINVAL;
8370 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008371 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008372 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8373 switch (config->channel_mask) {
8374 case AUDIO_CHANNEL_NONE:
8375 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8376 break;
8377 case AUDIO_CHANNEL_OUT_STEREO:
8378 out->channel_mask = config->channel_mask;
8379 break;
8380 default:
8381 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8382 config->channel_mask);
8383 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8384 ret = -EINVAL;
8385 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008386 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008387 switch (config->format) {
8388 case AUDIO_FORMAT_DEFAULT:
8389 out->format = AUDIO_FORMAT_PCM_16_BIT;
8390 break;
8391 case AUDIO_FORMAT_PCM_16_BIT:
8392 out->format = config->format;
8393 break;
8394 default:
8395 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8396 config->format);
8397 config->format = AUDIO_FORMAT_PCM_16_BIT;
8398 ret = -EINVAL;
8399 break;
8400 }
8401 if (ret != 0)
8402 goto error_open;
8403
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008404 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8405 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008406 out->config.rate = out->sample_rate;
8407 out->config.channels =
8408 audio_channel_count_from_out_mask(out->channel_mask);
8409 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008410 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008411 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308412 unsigned int channels = 0;
8413 /*Update config params to default if not set by the caller*/
8414 if (config->sample_rate == 0)
8415 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8416 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8417 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8418 if (config->format == AUDIO_FORMAT_DEFAULT)
8419 config->format = AUDIO_FORMAT_PCM_16_BIT;
8420
8421 channels = audio_channel_count_from_out_mask(out->channel_mask);
8422
Varun Balaraje49253e2017-07-06 19:48:56 +05308423 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8424 out->usecase = get_interactive_usecase(adev);
8425 out->config = pcm_config_low_latency;
8426 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308427 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008428 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8429 out->flags);
8430 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008431 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8432 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8433 out->config = pcm_config_mmap_playback;
8434 out->stream.start = out_start;
8435 out->stream.stop = out_stop;
8436 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8437 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308438 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8439 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008440 out->hal_output_suspend_supported =
8441 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8442 out->dynamic_pm_qos_config_supported =
8443 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8444 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008445 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8446 } else {
8447 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8448 //the mixer path will be a string similar to "low-latency-playback resume"
8449 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8450 strlcat(out->pm_qos_mixer_path,
8451 " resume", MAX_MIXER_PATH_LEN);
8452 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8453 out->pm_qos_mixer_path);
8454 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308455 out->config = pcm_config_low_latency;
8456 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8457 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8458 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308459 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8460 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8461 if (out->config.period_size <= 0) {
8462 ALOGE("Invalid configuration period size is not valid");
8463 ret = -EINVAL;
8464 goto error_open;
8465 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008466 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8467 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8468 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008469 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8470 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8471 out->config = pcm_config_haptics_audio;
8472 if (force_haptic_path)
8473 adev->haptics_config = pcm_config_haptics_audio;
8474 else
8475 adev->haptics_config = pcm_config_haptics;
8476
Meng Wangd08ce322020-04-02 08:59:20 +08008477 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008478 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8479
8480 if (force_haptic_path) {
8481 out->config.channels = 1;
8482 adev->haptics_config.channels = 1;
8483 } else
8484 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 -08008485 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008486 ret = audio_extn_auto_hal_open_output_stream(out);
8487 if (ret) {
8488 ALOGE("%s: Failed to open output stream for bus device", __func__);
8489 ret = -EINVAL;
8490 goto error_open;
8491 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308492 } else {
8493 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008494 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8495 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308496 }
8497 out->hal_ip_format = format = out->format;
8498 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8499 out->hal_op_format = pcm_format_to_hal(out->config.format);
8500 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8501 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008502 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308503 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308504 if (out->hal_ip_format != out->hal_op_format) {
8505 uint32_t buffer_size = out->config.period_size *
8506 format_to_bitwidth_table[out->hal_op_format] *
8507 out->config.channels;
8508 out->convert_buffer = calloc(1, buffer_size);
8509 if (out->convert_buffer == NULL){
8510 ALOGE("Allocation failed for convert buffer for size %d",
8511 out->compr_config.fragment_size);
8512 ret = -ENOMEM;
8513 goto error_open;
8514 }
8515 ALOGD("Convert buffer allocated of size %d", buffer_size);
8516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008517 }
8518
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008519 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8520 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308521
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008522 /* TODO remove this hardcoding and check why width is zero*/
8523 if (out->bit_width == 0)
8524 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308525 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008526 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008527 &out->device_list, out->flags,
8528 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308529 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308530 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008531 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008532 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8533 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008534 if(adev->primary_output == NULL)
8535 adev->primary_output = out;
8536 else {
8537 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008538 ret = -EEXIST;
8539 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008540 }
8541 }
8542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008543 /* Check if this usecase is already existing */
8544 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008545 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8546 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008547 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008548 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008549 ret = -EEXIST;
8550 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008551 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008553 pthread_mutex_unlock(&adev->lock);
8554
8555 out->stream.common.get_sample_rate = out_get_sample_rate;
8556 out->stream.common.set_sample_rate = out_set_sample_rate;
8557 out->stream.common.get_buffer_size = out_get_buffer_size;
8558 out->stream.common.get_channels = out_get_channels;
8559 out->stream.common.get_format = out_get_format;
8560 out->stream.common.set_format = out_set_format;
8561 out->stream.common.standby = out_standby;
8562 out->stream.common.dump = out_dump;
8563 out->stream.common.set_parameters = out_set_parameters;
8564 out->stream.common.get_parameters = out_get_parameters;
8565 out->stream.common.add_audio_effect = out_add_audio_effect;
8566 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8567 out->stream.get_latency = out_get_latency;
8568 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008569#ifdef NO_AUDIO_OUT
8570 out->stream.write = out_write_for_no_output;
8571#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008572 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008573#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008574 out->stream.get_render_position = out_get_render_position;
8575 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008576 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008577
Haynes Mathew George16081042017-05-31 17:16:49 -07008578 if (out->realtime)
8579 out->af_period_multiplier = af_period_multiplier;
8580 else
8581 out->af_period_multiplier = 1;
8582
Andy Hunga1f48fa2019-07-01 18:14:53 -07008583 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008585 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008586 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008587 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008588
8589 config->format = out->stream.common.get_format(&out->stream.common);
8590 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8591 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308592 register_format(out->format, out->supported_formats);
8593 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8594 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008595
Aalique Grahame22e49102018-12-18 14:23:57 -08008596 out->error_log = error_log_create(
8597 ERROR_LOG_ENTRIES,
8598 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8599
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308600 /*
8601 By locking output stream before registering, we allow the callback
8602 to update stream's state only after stream's initial state is set to
8603 adev state.
8604 */
8605 lock_output_stream(out);
8606 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8607 pthread_mutex_lock(&adev->lock);
8608 out->card_status = adev->card_status;
8609 pthread_mutex_unlock(&adev->lock);
8610 pthread_mutex_unlock(&out->lock);
8611
Aalique Grahame22e49102018-12-18 14:23:57 -08008612 stream_app_type_cfg_init(&out->app_type_cfg);
8613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008614 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308615 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008616 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008617
8618 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8619 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8620 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008621 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308622 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008623 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008624 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308625 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8626 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008627 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8628 out->usecase, PCM_PLAYBACK);
8629 hdlr_stream_cfg.flags = out->flags;
8630 hdlr_stream_cfg.type = PCM_PLAYBACK;
8631 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8632 &hdlr_stream_cfg);
8633 if (ret) {
8634 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8635 out->adsp_hdlr_stream_handle = NULL;
8636 }
8637 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308638 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8639 is_direct_passthough, false);
8640 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8641 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008642 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008643 if (ret < 0) {
8644 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8645 out->ip_hdlr_handle = NULL;
8646 }
8647 }
Derek Chenf939fb72018-11-13 13:34:41 -08008648
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008649 ret = io_streams_map_insert(adev, &out->stream.common,
8650 out->handle, AUDIO_PATCH_HANDLE_NONE);
8651 if (ret != 0)
8652 goto error_open;
8653
Derek Chenf939fb72018-11-13 13:34:41 -08008654 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8655 calloc(1, sizeof(streams_output_ctxt_t));
8656 if (out_ctxt == NULL) {
8657 ALOGE("%s fail to allocate output ctxt", __func__);
8658 ret = -ENOMEM;
8659 goto error_open;
8660 }
8661 out_ctxt->output = out;
8662
8663 pthread_mutex_lock(&adev->lock);
8664 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8665 pthread_mutex_unlock(&adev->lock);
8666
Eric Laurent994a6932013-07-17 11:51:42 -07008667 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008668 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008669
8670error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308671 if (out->convert_buffer)
8672 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008673 free(out);
8674 *stream_out = NULL;
8675 ALOGD("%s: exit: ret %d", __func__, ret);
8676 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008677}
8678
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308679void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008680 struct audio_stream_out *stream)
8681{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008682 struct stream_out *out = (struct stream_out *)stream;
8683 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008684 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008685
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008686 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308687
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008688 io_streams_map_remove(adev, out->handle);
8689
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308690 // must deregister from sndmonitor first to prevent races
8691 // between the callback and close_stream
8692 audio_extn_snd_mon_unregister_listener(out);
8693
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008694 /* close adsp hdrl session before standby */
8695 if (out->adsp_hdlr_stream_handle) {
8696 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8697 if (ret)
8698 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8699 out->adsp_hdlr_stream_handle = NULL;
8700 }
8701
Manish Dewangan21a850a2017-08-14 12:03:55 +05308702 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008703 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8704 out->ip_hdlr_handle = NULL;
8705 }
8706
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008707 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308708 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008709 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308710 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308711 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008712 if(ret != 0)
8713 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8714 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008715 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008716 out_standby(&stream->common);
8717
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008718 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008719 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008720 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008721 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008722 if (out->compr_config.codec != NULL)
8723 free(out->compr_config.codec);
8724 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008725
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308726 out->a2dp_compress_mute = false;
8727
Varun Balaraje49253e2017-07-06 19:48:56 +05308728 if (is_interactive_usecase(out->usecase))
8729 free_interactive_usecase(adev, out->usecase);
8730
Ashish Jain83a6cc22016-06-28 14:34:17 +05308731 if (out->convert_buffer != NULL) {
8732 free(out->convert_buffer);
8733 out->convert_buffer = NULL;
8734 }
8735
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008736 if (adev->voice_tx_output == out)
8737 adev->voice_tx_output = NULL;
8738
Aalique Grahame22e49102018-12-18 14:23:57 -08008739 error_log_destroy(out->error_log);
8740 out->error_log = NULL;
8741
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308742 if (adev->primary_output == out)
8743 adev->primary_output = NULL;
8744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008745 pthread_cond_destroy(&out->cond);
8746 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008747 pthread_mutex_destroy(&out->pre_lock);
8748 pthread_mutex_destroy(&out->latch_lock);
8749 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008750
8751 pthread_mutex_lock(&adev->lock);
8752 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8753 if (out_ctxt != NULL) {
8754 list_remove(&out_ctxt->list);
8755 free(out_ctxt);
8756 } else {
8757 ALOGW("%s, output stream already closed", __func__);
8758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008759 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008760 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008761 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762}
8763
8764static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8765{
8766 struct audio_device *adev = (struct audio_device *)dev;
8767 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008768 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008769 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008770 int ret;
8771 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008772 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008773 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008774 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008775
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008776 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008777 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008778
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308779 if (!parms)
8780 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308781
Derek Chen6f293672019-04-01 01:40:24 -07008782 /* notify adev and input/output streams on the snd card status */
8783 adev_snd_mon_cb((void *)adev, parms);
8784
8785 list_for_each(node, &adev->active_outputs_list) {
8786 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8787 streams_output_ctxt_t,
8788 list);
8789 out_snd_mon_cb((void *)out_ctxt->output, parms);
8790 }
8791
8792 list_for_each(node, &adev->active_inputs_list) {
8793 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8794 streams_input_ctxt_t,
8795 list);
8796 in_snd_mon_cb((void *)in_ctxt->input, parms);
8797 }
8798
Zhou Songd6d71752019-05-21 18:08:51 +08008799 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308800 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8801 if (ret >= 0) {
8802 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008803 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308804 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008805 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308806 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008807 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008808 }
8809 }
8810
8811 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008812 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008813 if (!strncmp(value, "false", 5) &&
8814 audio_extn_a2dp_source_is_suspended()) {
8815 struct audio_usecase *usecase;
8816 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008817 list_for_each(node, &adev->usecase_list) {
8818 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008819 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008820 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008821 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008822 reassign_device_list(&usecase->stream.in->device_list,
8823 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008824 select_devices(adev, usecase->id);
8825 }
Zhou Songd6d71752019-05-21 18:08:51 +08008826 }
8827 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308828 }
8829
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008830 status = voice_set_parameters(adev, parms);
8831 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008832 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008833
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008834 status = platform_set_parameters(adev->platform, parms);
8835 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008836 goto done;
8837
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008838 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8839 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008840 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008841 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8842 adev->bluetooth_nrec = true;
8843 else
8844 adev->bluetooth_nrec = false;
8845 }
8846
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008847 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8848 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008849 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8850 adev->screen_off = false;
8851 else
8852 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008853 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008854 }
8855
Eric Laurent4b084132018-10-19 17:33:43 -07008856 ret = str_parms_get_int(parms, "rotation", &val);
8857 if (ret >= 0) {
8858 bool reverse_speakers = false;
8859 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8860 switch (val) {
8861 // FIXME: note that the code below assumes that the speakers are in the correct placement
8862 // relative to the user when the device is rotated 90deg from its default rotation. This
8863 // assumption is device-specific, not platform-specific like this code.
8864 case 270:
8865 reverse_speakers = true;
8866 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8867 break;
8868 case 0:
8869 case 180:
8870 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8871 break;
8872 case 90:
8873 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8874 break;
8875 default:
8876 ALOGE("%s: unexpected rotation of %d", __func__, val);
8877 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008878 }
Eric Laurent4b084132018-10-19 17:33:43 -07008879 if (status == 0) {
8880 // check and set swap
8881 // - check if orientation changed and speaker active
8882 // - set rotation and cache the rotation value
8883 adev->camera_orientation =
8884 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8885 if (!audio_extn_is_maxx_audio_enabled())
8886 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8887 }
8888 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008889
Mingming Yin514a8bc2014-07-29 15:22:21 -07008890 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8891 if (ret >= 0) {
8892 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8893 adev->bt_wb_speech_enabled = true;
8894 else
8895 adev->bt_wb_speech_enabled = false;
8896 }
8897
Zhou Song12c29502019-03-16 10:37:18 +08008898 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8899 if (ret >= 0) {
8900 val = atoi(value);
8901 adev->swb_speech_mode = val;
8902 }
8903
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008904 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8905 if (ret >= 0) {
8906 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308907 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008908 if (audio_is_output_device(val) &&
8909 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008910 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008911 platform_get_controller_stream_from_params(parms, &controller, &stream);
8912 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8913 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008914 if (ret < 0) {
8915 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308916 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008917 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008918 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308919 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008920 /*
8921 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8922 * Per AudioPolicyManager, USB device is higher priority than WFD.
8923 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8924 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8925 * starting voice call on USB
8926 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008927 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308928 if (ret >= 0)
8929 audio_extn_usb_add_device(device, atoi(value));
8930
Zhou Song6f862822017-11-06 17:27:57 +08008931 if (!audio_extn_usb_is_tunnel_supported()) {
8932 ALOGV("detected USB connect .. disable proxy");
8933 adev->allow_afe_proxy_usage = false;
8934 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008935 }
8936 }
8937
8938 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8939 if (ret >= 0) {
8940 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308941 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008942 /*
8943 * The HDMI / Displayport disconnect handling has been moved to
8944 * audio extension to ensure that its parameters are not
8945 * invalidated prior to updating sysfs of the disconnect event
8946 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8947 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308948 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008949 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308950 if (ret >= 0)
8951 audio_extn_usb_remove_device(device, atoi(value));
8952
Zhou Song6f862822017-11-06 17:27:57 +08008953 if (!audio_extn_usb_is_tunnel_supported()) {
8954 ALOGV("detected USB disconnect .. enable proxy");
8955 adev->allow_afe_proxy_usage = true;
8956 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008957 }
8958 }
8959
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008960 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008961
8962 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008963 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308964 struct audio_usecase *usecase;
8965 struct listnode *node;
8966 list_for_each(node, &adev->usecase_list) {
8967 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008968 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8969 continue;
8970
8971 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308972 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308973 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308974 ALOGD("Switching to speaker and muting the stream before select_devices");
8975 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308976 //force device switch to re configure encoder
8977 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308978 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiang280ea742020-09-08 20:28:22 +08008979 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308980 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiang280ea742020-09-08 20:28:22 +08008981 out_set_compr_volume(&usecase->stream.out->stream,
8982 usecase->stream.out->volume_l,
8983 usecase->stream.out->volume_r);
8984 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308985 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308986 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008987 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008988 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8989 if (usecase->stream.out->a2dp_compress_mute) {
8990 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8991 reassign_device_list(&usecase->stream.out->device_list,
8992 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8993 check_a2dp_restore_l(adev, usecase->stream.out, true);
8994 break;
8995 }
8996 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308997 }
8998 }
8999 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009000
9001 //handle vr audio setparam
9002 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9003 value, sizeof(value));
9004 if (ret >= 0) {
9005 ALOGI("Setting vr mode to be %s", value);
9006 if (!strncmp(value, "true", 4)) {
9007 adev->vr_audio_mode_enabled = true;
9008 ALOGI("Setting vr mode to true");
9009 } else if (!strncmp(value, "false", 5)) {
9010 adev->vr_audio_mode_enabled = false;
9011 ALOGI("Setting vr mode to false");
9012 } else {
9013 ALOGI("wrong vr mode set");
9014 }
9015 }
9016
Eric Laurent4b084132018-10-19 17:33:43 -07009017 //FIXME: to be replaced by proper video capture properties API
9018 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9019 if (ret >= 0) {
9020 int camera_facing = CAMERA_FACING_BACK;
9021 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9022 camera_facing = CAMERA_FACING_FRONT;
9023 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9024 camera_facing = CAMERA_FACING_BACK;
9025 else {
9026 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9027 goto done;
9028 }
9029 adev->camera_orientation =
9030 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9031 struct audio_usecase *usecase;
9032 struct listnode *node;
9033 list_for_each(node, &adev->usecase_list) {
9034 usecase = node_to_item(node, struct audio_usecase, list);
9035 struct stream_in *in = usecase->stream.in;
9036 if (usecase->type == PCM_CAPTURE && in != NULL &&
9037 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9038 select_devices(adev, in->usecase);
9039 }
9040 }
9041 }
9042
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309043 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009044done:
9045 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009046 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309047error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009048 ALOGV("%s: exit with code(%d)", __func__, status);
9049 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009050}
9051
9052static char* adev_get_parameters(const struct audio_hw_device *dev,
9053 const char *keys)
9054{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309055 ALOGD("%s:%s", __func__, keys);
9056
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009057 struct audio_device *adev = (struct audio_device *)dev;
9058 struct str_parms *reply = str_parms_create();
9059 struct str_parms *query = str_parms_create_str(keys);
9060 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309061 char value[256] = {0};
9062 int ret = 0;
9063
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009064 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009065 if (reply) {
9066 str_parms_destroy(reply);
9067 }
9068 if (query) {
9069 str_parms_destroy(query);
9070 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009071 ALOGE("adev_get_parameters: failed to create query or reply");
9072 return NULL;
9073 }
9074
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009075 //handle vr audio getparam
9076
9077 ret = str_parms_get_str(query,
9078 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9079 value, sizeof(value));
9080
9081 if (ret >= 0) {
9082 bool vr_audio_enabled = false;
9083 pthread_mutex_lock(&adev->lock);
9084 vr_audio_enabled = adev->vr_audio_mode_enabled;
9085 pthread_mutex_unlock(&adev->lock);
9086
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009087 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009088
9089 if (vr_audio_enabled) {
9090 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9091 "true");
9092 goto exit;
9093 } else {
9094 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9095 "false");
9096 goto exit;
9097 }
9098 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009099
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009100 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009101 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009102 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009103 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009104 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009105 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309106 pthread_mutex_unlock(&adev->lock);
9107
Naresh Tannirud7205b62014-06-20 02:54:48 +05309108exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009109 str = str_parms_to_str(reply);
9110 str_parms_destroy(query);
9111 str_parms_destroy(reply);
9112
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009113 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009114 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009115}
9116
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009117static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009118{
9119 return 0;
9120}
9121
9122static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9123{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009124 int ret;
9125 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009126
9127 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9128
Haynes Mathew George5191a852013-09-11 14:19:36 -07009129 pthread_mutex_lock(&adev->lock);
9130 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009131 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009132 pthread_mutex_unlock(&adev->lock);
9133 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009134}
9135
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009136static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9137 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009138{
9139 return -ENOSYS;
9140}
9141
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009142static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9143 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144{
9145 return -ENOSYS;
9146}
9147
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009148static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9149 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009150{
9151 return -ENOSYS;
9152}
9153
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009154static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9155 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156{
9157 return -ENOSYS;
9158}
9159
9160static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9161{
9162 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009163 struct listnode *node;
9164 struct audio_usecase *usecase = NULL;
9165 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009167 pthread_mutex_lock(&adev->lock);
9168 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309169 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9170 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009172 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309173 adev->current_call_output = adev->primary_output;
9174 voice_start_call(adev);
9175 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009176 (mode == AUDIO_MODE_NORMAL ||
9177 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009178 list_for_each(node, &adev->usecase_list) {
9179 usecase = node_to_item(node, struct audio_usecase, list);
9180 if (usecase->type == VOICE_CALL)
9181 break;
9182 }
9183 if (usecase &&
9184 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9185 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9186 true);
9187 if (ret != 0) {
9188 /* default service interval was successfully updated,
9189 reopen USB backend with new service interval */
9190 check_usecases_codec_backend(adev,
9191 usecase,
9192 usecase->out_snd_device);
9193 }
9194 }
9195
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009196 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009197 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009198 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009199 // restore device for other active usecases after stop call
9200 list_for_each(node, &adev->usecase_list) {
9201 usecase = node_to_item(node, struct audio_usecase, list);
9202 select_devices(adev, usecase->id);
9203 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009205 }
9206 pthread_mutex_unlock(&adev->lock);
9207 return 0;
9208}
9209
9210static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9211{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009212 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009213 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009214
9215 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009216 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009217 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009218
Derek Chend2530072014-11-24 12:39:14 -08009219 if (adev->ext_hw_plugin)
9220 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009221
9222 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009223 pthread_mutex_unlock(&adev->lock);
9224
9225 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009226}
9227
9228static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9229{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009230 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231 return 0;
9232}
9233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009234static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009235 const struct audio_config *config)
9236{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009237 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009238
Aalique Grahame22e49102018-12-18 14:23:57 -08009239 /* Don't know if USB HIFI in this context so use true to be conservative */
9240 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9241 true /*is_usb_hifi */) != 0)
9242 return 0;
9243
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009244 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9245 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009246}
9247
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009248static bool adev_input_allow_hifi_record(struct audio_device *adev,
9249 audio_devices_t devices,
9250 audio_input_flags_t flags,
9251 audio_source_t source) {
9252 const bool allowed = true;
9253
9254 if (!audio_is_usb_in_device(devices))
9255 return !allowed;
9256
9257 switch (flags) {
9258 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009259 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009260 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9261 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009262 default:
9263 return !allowed;
9264 }
9265
9266 switch (source) {
9267 case AUDIO_SOURCE_DEFAULT:
9268 case AUDIO_SOURCE_MIC:
9269 case AUDIO_SOURCE_UNPROCESSED:
9270 break;
9271 default:
9272 return !allowed;
9273 }
9274
9275 switch (adev->mode) {
9276 case 0:
9277 break;
9278 default:
9279 return !allowed;
9280 }
9281
9282 return allowed;
9283}
9284
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009285static int adev_update_voice_comm_input_stream(struct stream_in *in,
9286 struct audio_config *config)
9287{
9288 bool valid_rate = (config->sample_rate == 8000 ||
9289 config->sample_rate == 16000 ||
9290 config->sample_rate == 32000 ||
9291 config->sample_rate == 48000);
9292 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9293
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009294 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009295 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009296 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9297 in->config = default_pcm_config_voip_copp;
9298 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9299 DEFAULT_VOIP_BUF_DURATION_MS,
9300 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009301 } else {
9302 ALOGW("%s No valid input in voip, use defaults"
9303 "sample rate %u, channel mask 0x%X",
9304 __func__, config->sample_rate, in->channel_mask);
9305 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009306 in->config.rate = config->sample_rate;
9307 in->sample_rate = config->sample_rate;
9308 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009309 //XXX needed for voice_extn_compress_voip_open_input_stream
9310 in->config.rate = config->sample_rate;
9311 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309312 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009313 voice_extn_compress_voip_is_active(in->dev)) &&
9314 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9315 valid_rate && valid_ch) {
9316 voice_extn_compress_voip_open_input_stream(in);
9317 // update rate entries to match config from AF
9318 in->config.rate = config->sample_rate;
9319 in->sample_rate = config->sample_rate;
9320 } else {
9321 ALOGW("%s compress voip not active, use defaults", __func__);
9322 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009323 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009324 return 0;
9325}
9326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009327static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009328 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009329 audio_devices_t devices,
9330 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009331 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309332 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009333 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009334 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009335{
9336 struct audio_device *adev = (struct audio_device *)dev;
9337 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009338 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009339 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009340 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309341 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009342 bool is_usb_dev = audio_is_usb_in_device(devices);
9343 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9344 devices,
9345 flags,
9346 source);
Andy Hung94320602018-10-29 18:31:12 -07009347 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9348 " sample_rate %u, channel_mask %#x, format %#x",
9349 __func__, flags, is_usb_dev, may_use_hifi_record,
9350 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309351
kunleizdff872d2018-08-20 14:40:33 +08009352 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009353 is_usb_dev = false;
9354 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9355 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9356 __func__, devices);
9357 }
9358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009359 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009360
9361 if (!(is_usb_dev && may_use_hifi_record)) {
9362 if (config->sample_rate == 0)
9363 config->sample_rate = 48000;
9364 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9365 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9366 if (config->format == AUDIO_FORMAT_DEFAULT)
9367 config->format = AUDIO_FORMAT_PCM_16_BIT;
9368
9369 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9370
Aalique Grahame22e49102018-12-18 14:23:57 -08009371 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9372 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009373 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009375
Rahul Sharma99770982019-03-06 17:05:26 +05309376 pthread_mutex_lock(&adev->lock);
9377 if (in_get_stream(adev, handle) != NULL) {
9378 ALOGW("%s, input stream already opened", __func__);
9379 ret = -EEXIST;
9380 }
9381 pthread_mutex_unlock(&adev->lock);
9382 if (ret)
9383 return ret;
9384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009385 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009386
9387 if (!in) {
9388 ALOGE("failed to allocate input stream");
9389 return -ENOMEM;
9390 }
9391
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309392 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309393 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9394 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009395 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009396 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009398 in->stream.common.get_sample_rate = in_get_sample_rate;
9399 in->stream.common.set_sample_rate = in_set_sample_rate;
9400 in->stream.common.get_buffer_size = in_get_buffer_size;
9401 in->stream.common.get_channels = in_get_channels;
9402 in->stream.common.get_format = in_get_format;
9403 in->stream.common.set_format = in_set_format;
9404 in->stream.common.standby = in_standby;
9405 in->stream.common.dump = in_dump;
9406 in->stream.common.set_parameters = in_set_parameters;
9407 in->stream.common.get_parameters = in_get_parameters;
9408 in->stream.common.add_audio_effect = in_add_audio_effect;
9409 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9410 in->stream.set_gain = in_set_gain;
9411 in->stream.read = in_read;
9412 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009413 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309414 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009415 in->stream.set_microphone_direction = in_set_microphone_direction;
9416 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009417 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009418
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009419 list_init(&in->device_list);
9420 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009421 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009422 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009423 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009424 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009425 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009426 in->bit_width = 16;
9427 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009428 in->direction = MIC_DIRECTION_UNSPECIFIED;
9429 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009430 list_init(&in->aec_list);
9431 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009432 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009433
Andy Hung94320602018-10-29 18:31:12 -07009434 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009435 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9436 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9437 /* Force channel config requested to mono if incall
9438 record is being requested for only uplink/downlink */
9439 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9440 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9441 ret = -EINVAL;
9442 goto err_open;
9443 }
9444 }
9445
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009446 if (is_usb_dev && may_use_hifi_record) {
9447 /* HiFi record selects an appropriate format, channel, rate combo
9448 depending on sink capabilities*/
9449 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9450 &config->format,
9451 &in->supported_formats[0],
9452 MAX_SUPPORTED_FORMATS,
9453 &config->channel_mask,
9454 &in->supported_channel_masks[0],
9455 MAX_SUPPORTED_CHANNEL_MASKS,
9456 &config->sample_rate,
9457 &in->supported_sample_rates[0],
9458 MAX_SUPPORTED_SAMPLE_RATES);
9459 if (ret != 0) {
9460 ret = -EINVAL;
9461 goto err_open;
9462 }
9463 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009464 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309465 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309466 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9467 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9468 in->config.format = PCM_FORMAT_S32_LE;
9469 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309470 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9471 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9472 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9473 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9474 bool ret_error = false;
9475 in->bit_width = 24;
9476 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9477 from HAL is 24_packed and 8_24
9478 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9479 24_packed return error indicating supported format is 24_packed
9480 *> In case of any other source requesting 24 bit or float return error
9481 indicating format supported is 16 bit only.
9482
9483 on error flinger will retry with supported format passed
9484 */
9485 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9486 (source != AUDIO_SOURCE_CAMCORDER)) {
9487 config->format = AUDIO_FORMAT_PCM_16_BIT;
9488 if (config->sample_rate > 48000)
9489 config->sample_rate = 48000;
9490 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009491 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9492 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309493 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9494 ret_error = true;
9495 }
9496
9497 if (ret_error) {
9498 ret = -EINVAL;
9499 goto err_open;
9500 }
9501 }
9502
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009503 in->channel_mask = config->channel_mask;
9504 in->format = config->format;
9505
9506 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309507
Huicheng Liu1404ba12020-09-11 01:03:25 -04009508 /* validate bus device address */
9509 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9510 /* extract car audio stream index */
9511 in->car_audio_stream =
9512 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9513 if (in->car_audio_stream < 0) {
9514 ALOGE("%s: invalid car audio stream %x",
9515 __func__, in->car_audio_stream);
9516 ret = -EINVAL;
9517 goto err_open;
9518 }
9519 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
9520 }
9521
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309522 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9523 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9524 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9525 else {
9526 ret = -EINVAL;
9527 goto err_open;
9528 }
9529 }
9530
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009531 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309532 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9533 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009534 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9535 is_low_latency = true;
9536#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309537 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9538 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9539 else
9540 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009541#endif
9542 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009543 if (!in->realtime) {
9544 in->config = pcm_config_audio_capture;
9545 frame_size = audio_stream_in_frame_size(&in->stream);
9546 buffer_size = get_input_buffer_size(config->sample_rate,
9547 config->format,
9548 channel_count,
9549 is_low_latency);
9550 in->config.period_size = buffer_size / frame_size;
9551 in->config.rate = config->sample_rate;
9552 in->af_period_multiplier = 1;
9553 } else {
9554 // period size is left untouched for rt mode playback
9555 in->config = pcm_config_audio_capture_rt;
9556 in->af_period_multiplier = af_period_multiplier;
9557 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009558 }
9559
9560 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9561 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9562 in->realtime = 0;
9563 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9564 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009565 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009566 in->stream.start = in_start;
9567 in->stream.stop = in_stop;
9568 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9569 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009570 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009571 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009572 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9573 in->config = pcm_config_audio_capture;
9574 frame_size = audio_stream_in_frame_size(&in->stream);
9575 buffer_size = get_input_buffer_size(config->sample_rate,
9576 config->format,
9577 channel_count,
9578 false /*is_low_latency*/);
9579 in->config.period_size = buffer_size / frame_size;
9580 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009581 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009582 switch (config->format) {
9583 case AUDIO_FORMAT_PCM_32_BIT:
9584 in->bit_width = 32;
9585 break;
9586 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9587 case AUDIO_FORMAT_PCM_8_24_BIT:
9588 in->bit_width = 24;
9589 break;
9590 default:
9591 in->bit_width = 16;
9592 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009593 } else if (is_single_device_type_equal(&in->device_list,
9594 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9595 is_single_device_type_equal(&in->device_list,
9596 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009597 if (config->sample_rate == 0)
9598 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9599 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9600 config->sample_rate != 8000) {
9601 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9602 ret = -EINVAL;
9603 goto err_open;
9604 }
9605 if (config->format == AUDIO_FORMAT_DEFAULT)
9606 config->format = AUDIO_FORMAT_PCM_16_BIT;
9607 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9608 config->format = AUDIO_FORMAT_PCM_16_BIT;
9609 ret = -EINVAL;
9610 goto err_open;
9611 }
9612
9613 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009614 if (adev->ha_proxy_enable &&
9615 is_single_device_type_equal(&in->device_list,
9616 AUDIO_DEVICE_IN_TELEPHONY_RX))
9617 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009618 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009619 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009620 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309621 } else if (in->realtime) {
9622 in->config = pcm_config_audio_capture_rt;
9623 in->config.format = pcm_format_from_audio_format(config->format);
9624 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009625 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9626 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9627 (config->sample_rate == 8000 ||
9628 config->sample_rate == 16000 ||
9629 config->sample_rate == 32000 ||
9630 config->sample_rate == 48000) &&
9631 channel_count == 1) {
9632 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9633 in->config = pcm_config_audio_capture;
9634 frame_size = audio_stream_in_frame_size(&in->stream);
9635 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9636 config->sample_rate,
9637 config->format,
9638 channel_count, false /*is_low_latency*/);
9639 in->config.period_size = buffer_size / frame_size;
9640 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9641 in->config.rate = config->sample_rate;
9642 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009643 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309644 int ret_val;
9645 pthread_mutex_lock(&adev->lock);
9646 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9647 in, config, &channel_mask_updated);
9648 pthread_mutex_unlock(&adev->lock);
9649
9650 if (!ret_val) {
9651 if (channel_mask_updated == true) {
9652 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9653 __func__, config->channel_mask);
9654 ret = -EINVAL;
9655 goto err_open;
9656 }
9657 ALOGD("%s: created multi-channel session succesfully",__func__);
9658 } else if (audio_extn_compr_cap_enabled() &&
9659 audio_extn_compr_cap_format_supported(config->format) &&
9660 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9661 audio_extn_compr_cap_init(in);
9662 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309663 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309664 if (ret)
9665 goto err_open;
9666 } else {
9667 in->config = pcm_config_audio_capture;
9668 in->config.rate = config->sample_rate;
9669 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309670 in->format = config->format;
9671 frame_size = audio_stream_in_frame_size(&in->stream);
9672 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009673 config->format,
9674 channel_count,
9675 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009676 /* prevent division-by-zero */
9677 if (frame_size == 0) {
9678 ALOGE("%s: Error frame_size==0", __func__);
9679 ret = -EINVAL;
9680 goto err_open;
9681 }
9682
Revathi Uddarajud2634032017-12-07 14:42:34 +05309683 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009684 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009685
Revathi Uddarajud2634032017-12-07 14:42:34 +05309686 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9687 /* optionally use VOIP usecase depending on config(s) */
9688 ret = adev_update_voice_comm_input_stream(in, config);
9689 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009690
Revathi Uddarajud2634032017-12-07 14:42:34 +05309691 if (ret) {
9692 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9693 goto err_open;
9694 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009695 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309696
9697 /* assign concurrent capture usecase if record has to caried out from
9698 * actual hardware input source */
9699 if (audio_extn_is_concurrent_capture_enabled() &&
9700 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309701 /* Acquire lock to avoid two concurrent use cases initialized to
9702 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009703
Samyak Jainc37062f2019-04-25 18:41:06 +05309704 if (in->usecase == USECASE_AUDIO_RECORD) {
9705 pthread_mutex_lock(&adev->lock);
9706 if (!(adev->pcm_record_uc_state)) {
9707 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9708 adev->pcm_record_uc_state = 1;
9709 pthread_mutex_unlock(&adev->lock);
9710 } else {
9711 pthread_mutex_unlock(&adev->lock);
9712 /* Assign compress record use case for second record */
9713 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9714 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9715 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9716 if (audio_extn_cin_applicable_stream(in)) {
9717 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309718 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309719 if (ret)
9720 goto err_open;
9721 }
9722 }
9723 }
kunleiz28c73e72019-03-27 17:24:04 +08009724 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009725 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9726 ret = audio_extn_auto_hal_open_input_stream(in);
9727 if (ret) {
9728 ALOGE("%s: Failed to open input stream for bus device", __func__);
9729 ret = -EINVAL;
9730 goto err_open;
9731 }
9732 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009733 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309734 if (audio_extn_ssr_get_stream() != in)
9735 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009736
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009737 in->sample_rate = in->config.rate;
9738
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309739 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9740 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009741 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009742 in->sample_rate, in->bit_width,
9743 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309744 register_format(in->format, in->supported_formats);
9745 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9746 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309747
Aalique Grahame22e49102018-12-18 14:23:57 -08009748 in->error_log = error_log_create(
9749 ERROR_LOG_ENTRIES,
9750 1000000000 /* aggregate consecutive identical errors within one second */);
9751
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009752 /* This stream could be for sound trigger lab,
9753 get sound trigger pcm if present */
9754 audio_extn_sound_trigger_check_and_get_session(in);
9755
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309756 lock_input_stream(in);
9757 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9758 pthread_mutex_lock(&adev->lock);
9759 in->card_status = adev->card_status;
9760 pthread_mutex_unlock(&adev->lock);
9761 pthread_mutex_unlock(&in->lock);
9762
Aalique Grahame22e49102018-12-18 14:23:57 -08009763 stream_app_type_cfg_init(&in->app_type_cfg);
9764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009765 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009766
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009767 ret = io_streams_map_insert(adev, &in->stream.common,
9768 handle, AUDIO_PATCH_HANDLE_NONE);
9769 if (ret != 0)
9770 goto err_open;
9771
Derek Chenf939fb72018-11-13 13:34:41 -08009772 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9773 calloc(1, sizeof(streams_input_ctxt_t));
9774 if (in_ctxt == NULL) {
9775 ALOGE("%s fail to allocate input ctxt", __func__);
9776 ret = -ENOMEM;
9777 goto err_open;
9778 }
9779 in_ctxt->input = in;
9780
9781 pthread_mutex_lock(&adev->lock);
9782 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9783 pthread_mutex_unlock(&adev->lock);
9784
Eric Laurent994a6932013-07-17 11:51:42 -07009785 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009786 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009787
9788err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309789 if (in->usecase == USECASE_AUDIO_RECORD) {
9790 pthread_mutex_lock(&adev->lock);
9791 adev->pcm_record_uc_state = 0;
9792 pthread_mutex_unlock(&adev->lock);
9793 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009794 free(in);
9795 *stream_in = NULL;
9796 return ret;
9797}
9798
9799static void adev_close_input_stream(struct audio_hw_device *dev,
9800 struct audio_stream_in *stream)
9801{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009802 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009803 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009804 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309805
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309806 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009807
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009808 if (in == NULL) {
9809 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9810 return;
9811 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009812 io_streams_map_remove(adev, in->capture_handle);
9813
kunleiz70e57612018-12-28 17:50:23 +08009814 /* must deregister from sndmonitor first to prevent races
9815 * between the callback and close_stream
9816 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309817 audio_extn_snd_mon_unregister_listener(stream);
9818
kunleiz70e57612018-12-28 17:50:23 +08009819 /* Disable echo reference if there are no active input, hfp call
9820 * and sound trigger while closing input stream
9821 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009822 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009823 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009824 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9825 struct listnode out_devices;
9826 list_init(&out_devices);
9827 platform_set_echo_reference(adev, false, &out_devices);
9828 } else
kunleiz70e57612018-12-28 17:50:23 +08009829 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309830
Weiyin Jiang2995f662019-04-17 14:25:12 +08009831 error_log_destroy(in->error_log);
9832 in->error_log = NULL;
9833
Pallavid7c7a272018-01-16 11:22:55 +05309834
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009835 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309836 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009837 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309838 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009839 if (ret != 0)
9840 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9841 __func__, ret);
9842 } else
9843 in_standby(&stream->common);
9844
Weiyin Jiang280ea742020-09-08 20:28:22 +08009845 pthread_mutex_destroy(&in->lock);
9846 pthread_mutex_destroy(&in->pre_lock);
9847
Revathi Uddarajud2634032017-12-07 14:42:34 +05309848 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309849 if (in->usecase == USECASE_AUDIO_RECORD) {
9850 adev->pcm_record_uc_state = 0;
9851 }
9852
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009853 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9854 adev->enable_voicerx = false;
9855 }
9856
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009857 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009858 audio_extn_ssr_deinit();
9859 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009860
Garmond Leunge2433c32017-09-28 21:51:22 -07009861 if (audio_extn_ffv_get_stream() == in) {
9862 audio_extn_ffv_stream_deinit();
9863 }
9864
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309865 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009866 audio_extn_compr_cap_format_supported(in->config.format))
9867 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309868
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309869 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309870 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009871
Mingming Yinfd7607b2016-01-22 12:48:44 -08009872 if (in->is_st_session) {
9873 ALOGV("%s: sound trigger pcm stop lab", __func__);
9874 audio_extn_sound_trigger_stop_lab(in);
9875 }
Derek Chenf939fb72018-11-13 13:34:41 -08009876 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9877 if (in_ctxt != NULL) {
9878 list_remove(&in_ctxt->list);
9879 free(in_ctxt);
9880 } else {
9881 ALOGW("%s, input stream already closed", __func__);
9882 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009883 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309884 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009885 return;
9886}
9887
Aalique Grahame22e49102018-12-18 14:23:57 -08009888/* verifies input and output devices and their capabilities.
9889 *
9890 * This verification is required when enabling extended bit-depth or
9891 * sampling rates, as not all qcom products support it.
9892 *
9893 * Suitable for calling only on initialization such as adev_open().
9894 * It fills the audio_device use_case_table[] array.
9895 *
9896 * Has a side-effect that it needs to configure audio routing / devices
9897 * in order to power up the devices and read the device parameters.
9898 * It does not acquire any hw device lock. Should restore the devices
9899 * back to "normal state" upon completion.
9900 */
9901static int adev_verify_devices(struct audio_device *adev)
9902{
9903 /* enumeration is a bit difficult because one really wants to pull
9904 * the use_case, device id, etc from the hidden pcm_device_table[].
9905 * In this case there are the following use cases and device ids.
9906 *
9907 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9908 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9909 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9910 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9911 * [USECASE_AUDIO_RECORD] = {0, 0},
9912 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9913 * [USECASE_VOICE_CALL] = {2, 2},
9914 *
9915 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9916 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9917 */
9918
9919 /* should be the usecases enabled in adev_open_input_stream() */
9920 static const int test_in_usecases[] = {
9921 USECASE_AUDIO_RECORD,
9922 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9923 };
9924 /* should be the usecases enabled in adev_open_output_stream()*/
9925 static const int test_out_usecases[] = {
9926 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9927 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9928 };
9929 static const usecase_type_t usecase_type_by_dir[] = {
9930 PCM_PLAYBACK,
9931 PCM_CAPTURE,
9932 };
9933 static const unsigned flags_by_dir[] = {
9934 PCM_OUT,
9935 PCM_IN,
9936 };
9937
9938 size_t i;
9939 unsigned dir;
9940 const unsigned card_id = adev->snd_card;
9941
9942 for (dir = 0; dir < 2; ++dir) {
9943 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9944 const unsigned flags_dir = flags_by_dir[dir];
9945 const size_t testsize =
9946 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9947 const int *testcases =
9948 dir ? test_in_usecases : test_out_usecases;
9949 const audio_devices_t audio_device =
9950 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9951
9952 for (i = 0; i < testsize; ++i) {
9953 const audio_usecase_t audio_usecase = testcases[i];
9954 int device_id;
9955 struct pcm_params **pparams;
9956 struct stream_out out;
9957 struct stream_in in;
9958 struct audio_usecase uc_info;
9959 int retval;
9960
9961 pparams = &adev->use_case_table[audio_usecase];
9962 pcm_params_free(*pparams); /* can accept null input */
9963 *pparams = NULL;
9964
9965 /* find the device ID for the use case (signed, for error) */
9966 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9967 if (device_id < 0)
9968 continue;
9969
9970 /* prepare structures for device probing */
9971 memset(&uc_info, 0, sizeof(uc_info));
9972 uc_info.id = audio_usecase;
9973 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009974 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009975 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009976 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009977 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009978 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009979 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9980 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009981 }
9982 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009983 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009984 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009985 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009986 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009987 uc_info.in_snd_device = SND_DEVICE_NONE;
9988 uc_info.out_snd_device = SND_DEVICE_NONE;
9989 list_add_tail(&adev->usecase_list, &uc_info.list);
9990
9991 /* select device - similar to start_(in/out)put_stream() */
9992 retval = select_devices(adev, audio_usecase);
9993 if (retval >= 0) {
9994 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9995#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009996 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009997 if (*pparams) {
9998 ALOGV("%s: (%s) card %d device %d", __func__,
9999 dir ? "input" : "output", card_id, device_id);
10000 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10001 } else {
10002 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10003 }
10004#endif
10005 }
10006
10007 /* deselect device - similar to stop_(in/out)put_stream() */
10008 /* 1. Get and set stream specific mixer controls */
10009 retval = disable_audio_route(adev, &uc_info);
10010 /* 2. Disable the rx device */
10011 retval = disable_snd_device(adev,
10012 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10013 list_remove(&uc_info.list);
10014 }
10015 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010016 return 0;
10017}
10018
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010019int update_patch(unsigned int num_sources,
10020 const struct audio_port_config *sources,
10021 unsigned int num_sinks,
10022 const struct audio_port_config *sinks,
10023 audio_patch_handle_t handle,
10024 struct audio_patch_info *p_info,
10025 patch_type_t patch_type, bool new_patch)
10026{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010027 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010028
10029 if (p_info == NULL) {
10030 ALOGE("%s: Invalid patch pointer", __func__);
10031 return -EINVAL;
10032 }
10033
10034 if (new_patch) {
10035 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10036 if (p_info->patch == NULL) {
10037 ALOGE("%s: Could not allocate patch", __func__);
10038 return -ENOMEM;
10039 }
10040 }
10041
10042 p_info->patch->id = handle;
10043 p_info->patch->num_sources = num_sources;
10044 p_info->patch->num_sinks = num_sinks;
10045
10046 for (int i = 0; i < num_sources; i++)
10047 p_info->patch->sources[i] = sources[i];
10048 for (int i = 0; i < num_sinks; i++)
10049 p_info->patch->sinks[i] = sinks[i];
10050
10051 p_info->patch_type = patch_type;
10052 return 0;
10053}
10054
10055audio_patch_handle_t generate_patch_handle()
10056{
10057 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10058 if (++patch_handle < 0)
10059 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10060 return patch_handle;
10061}
10062
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010063int adev_create_audio_patch(struct audio_hw_device *dev,
10064 unsigned int num_sources,
10065 const struct audio_port_config *sources,
10066 unsigned int num_sinks,
10067 const struct audio_port_config *sinks,
10068 audio_patch_handle_t *handle)
10069{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010070 int ret = 0;
10071 struct audio_device *adev = (struct audio_device *)dev;
10072 struct audio_patch_info *p_info = NULL;
10073 patch_type_t patch_type = PATCH_NONE;
10074 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10075 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10076 struct audio_stream_info *s_info = NULL;
10077 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010078 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10080 bool new_patch = false;
10081 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010082
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10084 num_sources, num_sinks, *handle);
10085
10086 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10087 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10088 ALOGE("%s: Invalid patch arguments", __func__);
10089 ret = -EINVAL;
10090 goto done;
10091 }
10092
10093 if (num_sources > 1) {
10094 ALOGE("%s: Multiple sources are not supported", __func__);
10095 ret = -EINVAL;
10096 goto done;
10097 }
10098
10099 if (sources == NULL || sinks == NULL) {
10100 ALOGE("%s: Invalid sources or sinks port config", __func__);
10101 ret = -EINVAL;
10102 goto done;
10103 }
10104
10105 ALOGV("%s: source role %d, source type %d", __func__,
10106 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010107 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010108
10109 // Populate source/sink information and fetch stream info
10110 switch (sources[0].type) {
10111 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10112 device_type = sources[0].ext.device.type;
10113 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010114 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010115 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10116 patch_type = PATCH_CAPTURE;
10117 io_handle = sinks[0].ext.mix.handle;
10118 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010119 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010120 __func__, device_type, io_handle);
10121 } else {
10122 // Device to device patch is not implemented.
10123 // This space will need changes if audio HAL
10124 // handles device to device patches in the future.
10125 patch_type = PATCH_DEVICE_LOOPBACK;
10126 }
10127 break;
10128 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10129 io_handle = sources[0].ext.mix.handle;
10130 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010131 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010132 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010133 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010134 }
10135 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010136 ALOGD("%s: Playback patch from mix handle %d to device %x",
10137 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010138 break;
10139 case AUDIO_PORT_TYPE_SESSION:
10140 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010141 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10142 ret = -EINVAL;
10143 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144 }
10145
10146 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010148 // Generate patch info and update patch
10149 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010150 *handle = generate_patch_handle();
10151 p_info = (struct audio_patch_info *)
10152 calloc(1, sizeof(struct audio_patch_info));
10153 if (p_info == NULL) {
10154 ALOGE("%s: Failed to allocate memory", __func__);
10155 pthread_mutex_unlock(&adev->lock);
10156 ret = -ENOMEM;
10157 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010158 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010159 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010160 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010161 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 if (p_info == NULL) {
10163 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10164 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010165 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010166 ret = -EINVAL;
10167 goto done;
10168 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010170 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010171 *handle, p_info, patch_type, new_patch);
10172
10173 // Fetch stream info of associated mix for playback or capture patches
10174 if (p_info->patch_type == PATCH_PLAYBACK ||
10175 p_info->patch_type == PATCH_CAPTURE) {
10176 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10177 if (s_info == NULL) {
10178 ALOGE("%s: Failed to obtain stream info", __func__);
10179 if (new_patch)
10180 free(p_info);
10181 pthread_mutex_unlock(&adev->lock);
10182 ret = -EINVAL;
10183 goto done;
10184 }
10185 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10186 s_info->patch_handle = *handle;
10187 stream = s_info->stream;
10188 }
10189 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010190
10191 // Update routing for stream
10192 if (stream != NULL) {
10193 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010194 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010196 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010197 if (ret < 0) {
10198 pthread_mutex_lock(&adev->lock);
10199 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10200 if (new_patch)
10201 free(p_info);
10202 pthread_mutex_unlock(&adev->lock);
10203 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10204 goto done;
10205 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010206 }
10207
10208 // Add new patch to patch map
10209 if (!ret && new_patch) {
10210 pthread_mutex_lock(&adev->lock);
10211 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010213 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010214 }
10215
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010216done:
10217 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010218 num_sources,
10219 sources,
10220 num_sinks,
10221 sinks,
10222 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010223 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010224 num_sources,
10225 sources,
10226 num_sinks,
10227 sinks,
10228 handle);
10229 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010230}
10231
10232int adev_release_audio_patch(struct audio_hw_device *dev,
10233 audio_patch_handle_t handle)
10234{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010235 struct audio_device *adev = (struct audio_device *) dev;
10236 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010237 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010238 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010239
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010240 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10241 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10242 ret = -EINVAL;
10243 goto done;
10244 }
10245
10246 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010247 pthread_mutex_lock(&adev->lock);
10248 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010249 if (p_info == NULL) {
10250 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010251 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010252 ret = -EINVAL;
10253 goto done;
10254 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010255 struct audio_patch *patch = p_info->patch;
10256 if (patch == NULL) {
10257 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010258 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010259 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010260 goto done;
10261 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010262 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10263 switch (patch->sources[0].type) {
10264 case AUDIO_PORT_TYPE_MIX:
10265 io_handle = patch->sources[0].ext.mix.handle;
10266 break;
10267 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010268 if (p_info->patch_type == PATCH_CAPTURE)
10269 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010270 break;
10271 case AUDIO_PORT_TYPE_SESSION:
10272 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010273 pthread_mutex_unlock(&adev->lock);
10274 ret = -EINVAL;
10275 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010276 }
10277
10278 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010279 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010280 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010281 if (patch_type == PATCH_PLAYBACK ||
10282 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010283 struct audio_stream_info *s_info =
10284 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10285 if (s_info == NULL) {
10286 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10287 pthread_mutex_unlock(&adev->lock);
10288 goto done;
10289 }
10290 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10291 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010292 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010293 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010294
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010295 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010296 struct listnode devices;
10297 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010298 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010299 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010300 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010301 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010302 }
10303
10304 if (ret < 0)
10305 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10306
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010307done:
10308 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10309 audio_extn_auto_hal_release_audio_patch(dev, handle);
10310
10311 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010312 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010313}
10314
10315int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10316{
Derek Chenf13dd492018-11-13 14:53:51 -080010317 int ret = 0;
10318
10319 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10320 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10321 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010322}
10323
10324int adev_set_audio_port_config(struct audio_hw_device *dev,
10325 const struct audio_port_config *config)
10326{
Derek Chenf13dd492018-11-13 14:53:51 -080010327 int ret = 0;
10328
10329 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10330 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10331 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010332}
10333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010334static int adev_dump(const audio_hw_device_t *device __unused,
10335 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010336{
10337 return 0;
10338}
10339
10340static int adev_close(hw_device_t *device)
10341{
Aalique Grahame22e49102018-12-18 14:23:57 -080010342 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010343 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010344
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010345 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010346 return 0;
10347
10348 pthread_mutex_lock(&adev_init_lock);
10349
10350 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010351 if (audio_extn_spkr_prot_is_enabled())
10352 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010353 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010354 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010355 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010356 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010357 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010358 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010359 audio_extn_utils_release_streams_cfg_lists(
10360 &adev->streams_output_cfg_list,
10361 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010362 if (audio_extn_qap_is_enabled())
10363 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010364 if (audio_extn_qaf_is_enabled())
10365 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010366 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010367 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010368 free(adev->snd_dev_ref_cnt);
10369 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010370 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10371 pcm_params_free(adev->use_case_table[i]);
10372 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010373 if (adev->adm_deinit)
10374 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010375 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010376 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010377 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010378 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010379 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010380 if (adev->device_cfg_params) {
10381 free(adev->device_cfg_params);
10382 adev->device_cfg_params = NULL;
10383 }
Derek Chend2530072014-11-24 12:39:14 -080010384 if(adev->ext_hw_plugin)
10385 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010386 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010387 free_map(adev->patch_map);
10388 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010389 free(device);
10390 adev = NULL;
10391 }
10392 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010393 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010394 return 0;
10395}
10396
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010397/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10398 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10399 * just that it _might_ work.
10400 */
10401static int period_size_is_plausible_for_low_latency(int period_size)
10402{
10403 switch (period_size) {
10404 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010405 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010406 case 240:
10407 case 320:
10408 case 480:
10409 return 1;
10410 default:
10411 return 0;
10412 }
10413}
10414
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010415static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10416{
10417 bool is_snd_card_status = false;
10418 bool is_ext_device_status = false;
10419 char value[32];
10420 int card = -1;
10421 card_status_t status;
10422
10423 if (cookie != adev || !parms)
10424 return;
10425
10426 if (!parse_snd_card_status(parms, &card, &status)) {
10427 is_snd_card_status = true;
10428 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10429 is_ext_device_status = true;
10430 } else {
10431 // not a valid event
10432 return;
10433 }
10434
10435 pthread_mutex_lock(&adev->lock);
10436 if (card == adev->snd_card || is_ext_device_status) {
10437 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010438 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010439 adev->card_status = status;
10440 platform_snd_card_update(adev->platform, status);
10441 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010442 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010443 if (status == CARD_STATUS_OFFLINE)
10444 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010445 } else if (is_ext_device_status) {
10446 platform_set_parameters(adev->platform, parms);
10447 }
10448 }
10449 pthread_mutex_unlock(&adev->lock);
10450 return;
10451}
10452
Weiyin Jiang280ea742020-09-08 20:28:22 +080010453/* adev lock held */
10454int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010455{
10456 struct audio_usecase *uc_info;
10457 float left_p;
10458 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010459 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010460
10461 uc_info = get_usecase_from_list(adev, out->usecase);
10462 if (uc_info == NULL) {
10463 ALOGE("%s: Could not find the usecase (%d) in the list",
10464 __func__, out->usecase);
10465 return -EINVAL;
10466 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010467 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010468
10469 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10470 out->usecase, use_case_table[out->usecase]);
10471
10472 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010473 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010474 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010475 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010476 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010477 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10478 select_devices(adev, uc_info->id);
Zhou Songd01e7a22020-09-23 22:49:01 +080010479 if (is_offload_usecase(out->usecase) &&
Weiyin Jiang280ea742020-09-08 20:28:22 +080010480 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10481 if (out->a2dp_compress_mute) {
10482 out->a2dp_compress_mute = false;
10483 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10484 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010485 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010486 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010487 out->muted = false;
10488 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010489 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010490 pthread_mutex_lock(&out->latch_lock);
Zhou Songd01e7a22020-09-23 22:49:01 +080010491 if (is_offload_usecase(out->usecase)) {
Zhou Songc576a452019-09-09 14:17:40 +080010492 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010493 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010494 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010495 assign_devices(&devices, &out->device_list);
10496 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010497 left_p = out->volume_l;
10498 right_p = out->volume_r;
10499 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10500 compress_pause(out->compr);
10501 out_set_compr_volume(&out->stream, (float)0, (float)0);
10502 out->a2dp_compress_mute = true;
10503 select_devices(adev, out->usecase);
10504 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10505 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010506 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010507 out->volume_l = left_p;
10508 out->volume_r = right_p;
10509 }
Zhou Songc576a452019-09-09 14:17:40 +080010510 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010511 // mute for non offloaded streams
10512 if (audio_extn_a2dp_source_is_suspended()) {
10513 out->muted = true;
10514 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010515 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010516 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010517 }
10518 ALOGV("%s: exit", __func__);
10519 return 0;
10520}
10521
Haynes Mathew George01156f92018-04-13 15:29:54 -070010522void adev_on_battery_status_changed(bool charging)
10523{
10524 pthread_mutex_lock(&adev->lock);
10525 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10526 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010527 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010528 pthread_mutex_unlock(&adev->lock);
10529}
10530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010531static int adev_open(const hw_module_t *module, const char *name,
10532 hw_device_t **device)
10533{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010534 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010535 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010536 char mixer_ctl_name[128] = {0};
10537 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010538
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010539 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010540 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10541
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010542 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010543 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010544 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010545 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010546 ALOGD("%s: returning existing instance of adev", __func__);
10547 ALOGD("%s: exit", __func__);
10548 pthread_mutex_unlock(&adev_init_lock);
10549 return 0;
10550 }
10551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010552 adev = calloc(1, sizeof(struct audio_device));
10553
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010554 if (!adev) {
10555 pthread_mutex_unlock(&adev_init_lock);
10556 return -ENOMEM;
10557 }
10558
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010559 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10560
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010561 // register audio ext hidl at the earliest
10562 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010563#ifdef DYNAMIC_LOG_ENABLED
10564 register_for_dynamic_logging("hal");
10565#endif
10566
Derek Chenf939fb72018-11-13 13:34:41 -080010567 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010568 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010569 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10570 maj_version = atoi(value);
10571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010572 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010573 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010574 adev->device.common.module = (struct hw_module_t *)module;
10575 adev->device.common.close = adev_close;
10576
10577 adev->device.init_check = adev_init_check;
10578 adev->device.set_voice_volume = adev_set_voice_volume;
10579 adev->device.set_master_volume = adev_set_master_volume;
10580 adev->device.get_master_volume = adev_get_master_volume;
10581 adev->device.set_master_mute = adev_set_master_mute;
10582 adev->device.get_master_mute = adev_get_master_mute;
10583 adev->device.set_mode = adev_set_mode;
10584 adev->device.set_mic_mute = adev_set_mic_mute;
10585 adev->device.get_mic_mute = adev_get_mic_mute;
10586 adev->device.set_parameters = adev_set_parameters;
10587 adev->device.get_parameters = adev_get_parameters;
10588 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10589 adev->device.open_output_stream = adev_open_output_stream;
10590 adev->device.close_output_stream = adev_close_output_stream;
10591 adev->device.open_input_stream = adev_open_input_stream;
10592 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010593 adev->device.create_audio_patch = adev_create_audio_patch;
10594 adev->device.release_audio_patch = adev_release_audio_patch;
10595 adev->device.get_audio_port = adev_get_audio_port;
10596 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010597 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010598 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010599
10600 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010601 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010602 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010603 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010604 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010605 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010606 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010607 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010608 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010609 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010610 /* Init audio and voice feature */
10611 audio_extn_feature_init();
10612 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010613 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010614 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010615 list_init(&adev->active_inputs_list);
10616 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010617 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010618 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10619 audio_extn_utils_hash_eq);
10620 if (!adev->io_streams_map) {
10621 ALOGE("%s: Could not create io streams map", __func__);
10622 ret = -ENOMEM;
10623 goto adev_open_err;
10624 }
10625 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10626 audio_extn_utils_hash_eq);
10627 if (!adev->patch_map) {
10628 ALOGE("%s: Could not create audio patch map", __func__);
10629 ret = -ENOMEM;
10630 goto adev_open_err;
10631 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010632 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010633 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010634 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010635 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010636 adev->perf_lock_opts[0] = 0x101;
10637 adev->perf_lock_opts[1] = 0x20E;
10638 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010639 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010640 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010641 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010642 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010643 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010644
Zhou Song68ebc352019-12-05 17:11:15 +080010645 audio_extn_perf_lock_init();
10646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010647 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010648 adev->platform = platform_init(adev);
10649 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010650 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010651 ret = -EINVAL;
10652 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010653 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010654
Aalique Grahame22e49102018-12-18 14:23:57 -080010655 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010656 if (audio_extn_qap_is_enabled()) {
10657 ret = audio_extn_qap_init(adev);
10658 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010659 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010660 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010661 }
10662 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10663 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10664 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010665
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010666 if (audio_extn_qaf_is_enabled()) {
10667 ret = audio_extn_qaf_init(adev);
10668 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010669 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010670 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010671 }
10672
10673 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10674 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10675 }
10676
Derek Chenae7b0342019-02-08 15:17:04 -080010677 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010678 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10679
Eric Laurentc4aef752013-09-12 17:45:53 -070010680 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10681 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10682 if (adev->visualizer_lib == NULL) {
10683 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10684 } else {
10685 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10686 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010687 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010688 "visualizer_hal_start_output");
10689 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010690 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010691 "visualizer_hal_stop_output");
10692 }
10693 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010694 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010695 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010696 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010697 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010698 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010699 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010700
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010701 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10702 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10703 if (adev->offload_effects_lib == NULL) {
10704 ALOGE("%s: DLOPEN failed for %s", __func__,
10705 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10706 } else {
10707 ALOGV("%s: DLOPEN successful for %s", __func__,
10708 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10709 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010710 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010711 "offload_effects_bundle_hal_start_output");
10712 adev->offload_effects_stop_output =
10713 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10714 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010715 adev->offload_effects_set_hpx_state =
10716 (int (*)(bool))dlsym(adev->offload_effects_lib,
10717 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010718 adev->offload_effects_get_parameters =
10719 (void (*)(struct str_parms *, struct str_parms *))
10720 dlsym(adev->offload_effects_lib,
10721 "offload_effects_bundle_get_parameters");
10722 adev->offload_effects_set_parameters =
10723 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10724 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010725 }
10726 }
10727
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010728 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10729 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10730 if (adev->adm_lib == NULL) {
10731 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10732 } else {
10733 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10734 adev->adm_init = (adm_init_t)
10735 dlsym(adev->adm_lib, "adm_init");
10736 adev->adm_deinit = (adm_deinit_t)
10737 dlsym(adev->adm_lib, "adm_deinit");
10738 adev->adm_register_input_stream = (adm_register_input_stream_t)
10739 dlsym(adev->adm_lib, "adm_register_input_stream");
10740 adev->adm_register_output_stream = (adm_register_output_stream_t)
10741 dlsym(adev->adm_lib, "adm_register_output_stream");
10742 adev->adm_deregister_stream = (adm_deregister_stream_t)
10743 dlsym(adev->adm_lib, "adm_deregister_stream");
10744 adev->adm_request_focus = (adm_request_focus_t)
10745 dlsym(adev->adm_lib, "adm_request_focus");
10746 adev->adm_abandon_focus = (adm_abandon_focus_t)
10747 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010748 adev->adm_set_config = (adm_set_config_t)
10749 dlsym(adev->adm_lib, "adm_set_config");
10750 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10751 dlsym(adev->adm_lib, "adm_request_focus_v2");
10752 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10753 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10754 adev->adm_on_routing_change = (adm_on_routing_change_t)
10755 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010756 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10757 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010758 }
10759 }
10760
Aalique Grahame22e49102018-12-18 14:23:57 -080010761 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010762 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010763 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010764 //initialize this to false for now,
10765 //this will be set to true through set param
10766 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010767
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010768 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010769 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010770
10771 if (k_enable_extended_precision)
10772 adev_verify_devices(adev);
10773
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010774 adev->dsp_bit_width_enforce_mode =
10775 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010776
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010777 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10778 &adev->streams_output_cfg_list,
10779 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010780
Kiran Kandi910e1862013-10-29 13:29:42 -070010781 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010782
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010783 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010784 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010785 trial = atoi(value);
10786 if (period_size_is_plausible_for_low_latency(trial)) {
10787 pcm_config_low_latency.period_size = trial;
10788 pcm_config_low_latency.start_threshold = trial / 4;
10789 pcm_config_low_latency.avail_min = trial / 4;
10790 configured_low_latency_capture_period_size = trial;
10791 }
10792 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010793 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10794 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010795 trial = atoi(value);
10796 if (period_size_is_plausible_for_low_latency(trial)) {
10797 configured_low_latency_capture_period_size = trial;
10798 }
10799 }
10800
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010801 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10802
Eric Laurent4b084132018-10-19 17:33:43 -070010803 adev->camera_orientation = CAMERA_DEFAULT;
10804
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010805 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010806 af_period_multiplier = atoi(value);
10807 if (af_period_multiplier < 0)
10808 af_period_multiplier = 2;
10809 else if (af_period_multiplier > 4)
10810 af_period_multiplier = 4;
10811
10812 ALOGV("new period_multiplier = %d", af_period_multiplier);
10813 }
10814
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010815 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010816
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010817 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010818 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010819 pthread_mutex_unlock(&adev_init_lock);
10820
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010821 if (adev->adm_init)
10822 adev->adm_data = adev->adm_init();
10823
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010824 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010825 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010826
10827 audio_extn_snd_mon_init();
10828 pthread_mutex_lock(&adev->lock);
10829 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10830 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010831 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10832 /*
10833 * if the battery state callback happens before charging can be queried,
10834 * it will be guarded with the adev->lock held in the cb function and so
10835 * the callback value will reflect the latest state
10836 */
10837 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010838 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010839 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010840 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010841 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010842 /* Allocate memory for Device config params */
10843 adev->device_cfg_params = (struct audio_device_config_param*)
10844 calloc(platform_get_max_codec_backend(),
10845 sizeof(struct audio_device_config_param));
10846 if (adev->device_cfg_params == NULL)
10847 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010848
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010849 /*
10850 * Check if new PSPD matrix mixer control is supported. If not
10851 * supported, then set flag so that old mixer ctrl is sent while
10852 * sending pspd coefficients on older kernel version. Query mixer
10853 * control for default pcm id and channel value one.
10854 */
10855 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10856 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10857
10858 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10859 if (!ctl) {
10860 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10861 __func__, mixer_ctl_name);
10862 adev->use_old_pspd_mix_ctrl = true;
10863 }
10864
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010865 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010866 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010867
10868adev_open_err:
10869 free_map(adev->patch_map);
10870 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010871 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010872 pthread_mutex_destroy(&adev->lock);
10873 free(adev);
10874 adev = NULL;
10875 *device = NULL;
10876 pthread_mutex_unlock(&adev_init_lock);
10877 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010878}
10879
10880static struct hw_module_methods_t hal_module_methods = {
10881 .open = adev_open,
10882};
10883
10884struct audio_module HAL_MODULE_INFO_SYM = {
10885 .common = {
10886 .tag = HARDWARE_MODULE_TAG,
10887 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10888 .hal_api_version = HARDWARE_HAL_API_VERSION,
10889 .id = AUDIO_HARDWARE_MODULE_ID,
10890 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010891 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010892 .methods = &hal_module_methods,
10893 },
10894};