blob: 516584937e210d5a688387494db200b87c90b5a9 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530402 /* For Interactive Audio Streams */
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700411
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800412 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
413
Derek Chenf6318be2017-06-12 17:16:24 -0400414 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
415
416 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
417 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
418 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
419 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800420 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700421 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530422 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700423};
424
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700425static const audio_usecase_t offload_usecases[] = {
426 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700435};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436
Varun Balaraje49253e2017-07-06 19:48:56 +0530437static const audio_usecase_t interactive_usecases[] = {
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
446};
447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448#define STRING_TO_ENUM(string) { #string, string }
449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450struct string_to_enum {
451 const char *name;
452 uint32_t value;
453};
454
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800475};
476
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700477static const struct string_to_enum formats_name_to_enum_table[] = {
478 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700481 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
482 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700484 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800485 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
486 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700487 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800488};
489
490//list of all supported sample rates by HDMI specification.
491static const int out_hdmi_sample_rates[] = {
492 32000, 44100, 48000, 88200, 96000, 176400, 192000,
493};
494
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700495static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800496 STRING_TO_ENUM(32000),
497 STRING_TO_ENUM(44100),
498 STRING_TO_ENUM(48000),
499 STRING_TO_ENUM(88200),
500 STRING_TO_ENUM(96000),
501 STRING_TO_ENUM(176400),
502 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800503 STRING_TO_ENUM(352800),
504 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700505};
506
Carter Hsu2e429db2019-05-14 18:50:52 +0800507struct in_effect_list {
508 struct listnode list;
509 effect_handle_t handle;
510};
511
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700512static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700513static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700514static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700515//cache last MBDRC cal step level
516static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700517
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700519static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800520static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530521static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530522
Derek Chen6f293672019-04-01 01:40:24 -0700523static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
524static void in_snd_mon_cb(void * stream, struct str_parms * parms);
525static void out_snd_mon_cb(void * stream, struct str_parms * parms);
526
Zhou Song331c8e52019-08-26 14:16:12 +0800527static int configure_btsco_sample_rate(snd_device_t snd_device);
528
Vatsal Buchac09ae062018-11-14 13:25:08 +0530529#ifdef AUDIO_FEATURE_ENABLED_GCOV
530extern void __gcov_flush();
531static void enable_gcov()
532{
533 __gcov_flush();
534}
535#else
536static void enable_gcov()
537{
538}
539#endif
540
justinweng20fb6d82019-02-21 18:49:00 -0700541static int in_set_microphone_direction(const struct audio_stream_in *stream,
542 audio_microphone_direction_t dir);
543static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
544
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700545static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
546 int flags __unused)
547{
548 int dir = 0;
549 switch (uc_id) {
550 case USECASE_AUDIO_RECORD_LOW_LATENCY:
551 dir = 1;
552 case USECASE_AUDIO_PLAYBACK_ULL:
553 break;
554 default:
555 return false;
556 }
557
558 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
559 PCM_PLAYBACK : PCM_CAPTURE);
560 if (adev->adm_is_noirq_avail)
561 return adev->adm_is_noirq_avail(adev->adm_data,
562 adev->snd_card, dev_id, dir);
563 return false;
564}
565
566static void register_out_stream(struct stream_out *out)
567{
568 struct audio_device *adev = out->dev;
569 if (is_offload_usecase(out->usecase) ||
570 !adev->adm_register_output_stream)
571 return;
572
573 // register stream first for backward compatibility
574 adev->adm_register_output_stream(adev->adm_data,
575 out->handle,
576 out->flags);
577
578 if (!adev->adm_set_config)
579 return;
580
581 if (out->realtime)
582 adev->adm_set_config(adev->adm_data,
583 out->handle,
584 out->pcm, &out->config);
585}
586
587static void register_in_stream(struct stream_in *in)
588{
589 struct audio_device *adev = in->dev;
590 if (!adev->adm_register_input_stream)
591 return;
592
593 adev->adm_register_input_stream(adev->adm_data,
594 in->capture_handle,
595 in->flags);
596
597 if (!adev->adm_set_config)
598 return;
599
600 if (in->realtime)
601 adev->adm_set_config(adev->adm_data,
602 in->capture_handle,
603 in->pcm,
604 &in->config);
605}
606
607static void request_out_focus(struct stream_out *out, long ns)
608{
609 struct audio_device *adev = out->dev;
610
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611 if (adev->adm_request_focus_v2)
612 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
613 else if (adev->adm_request_focus)
614 adev->adm_request_focus(adev->adm_data, out->handle);
615}
616
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700617static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618{
619 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700622 if (adev->adm_request_focus_v2_1)
623 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
624 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700625 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
626 else if (adev->adm_request_focus)
627 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700628
629 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700630}
631
632static void release_out_focus(struct stream_out *out)
633{
634 struct audio_device *adev = out->dev;
635
636 if (adev->adm_abandon_focus)
637 adev->adm_abandon_focus(adev->adm_data, out->handle);
638}
639
640static void release_in_focus(struct stream_in *in)
641{
642 struct audio_device *adev = in->dev;
643 if (adev->adm_abandon_focus)
644 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
645}
646
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530647static int parse_snd_card_status(struct str_parms *parms, int *card,
648 card_status_t *status)
649{
650 char value[32]={0};
651 char state[32]={0};
652
653 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
654 if (ret < 0)
655 return -1;
656
657 // sscanf should be okay as value is of max length 32.
658 // same as sizeof state.
659 if (sscanf(value, "%d,%s", card, state) < 2)
660 return -1;
661
662 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
663 CARD_STATUS_OFFLINE;
664 return 0;
665}
666
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700667static inline void adjust_frames_for_device_delay(struct stream_out *out,
668 uint32_t *dsp_frames) {
669 // Adjustment accounts for A2dp encoder latency with offload usecases
670 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800671 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700672 unsigned long offset =
673 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
674 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
675 }
676}
677
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700678static inline bool free_entry(void *key __unused,
679 void *value, void *context __unused)
680{
681 free(value);
682 return true;
683}
684
685static inline void free_map(Hashmap *map)
686{
687 if (map) {
688 hashmapForEach(map, free_entry, (void *) NULL);
689 hashmapFree(map);
690 }
691}
692
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800693static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700694 audio_patch_handle_t patch_handle)
695{
696 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
697 return;
698
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699 struct audio_patch_info *p_info =
700 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
701 if (p_info) {
702 ALOGV("%s: Remove patch %d", __func__, patch_handle);
703 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
704 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700705 free(p_info);
706 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700707}
708
709static inline int io_streams_map_insert(struct audio_device *adev,
710 struct audio_stream *stream,
711 audio_io_handle_t handle,
712 audio_patch_handle_t patch_handle)
713{
714 struct audio_stream_info *s_info =
715 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
716
717 if (s_info == NULL) {
718 ALOGE("%s: Could not allocate stream info", __func__);
719 return -ENOMEM;
720 }
721 s_info->stream = stream;
722 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723
724 pthread_mutex_lock(&adev->lock);
725 struct audio_stream_info *stream_info =
726 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700727 if (stream_info != NULL)
728 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800729 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
731 return 0;
732}
733
734static inline void io_streams_map_remove(struct audio_device *adev,
735 audio_io_handle_t handle)
736{
737 pthread_mutex_lock(&adev->lock);
738 struct audio_stream_info *s_info =
739 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700742 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800743 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700744 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800745done:
746 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 return;
748}
749
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800750static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700751 audio_patch_handle_t handle)
752{
753 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 p_info = (struct audio_patch_info *)
755 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700756 return p_info;
757}
758
vivek mehtaa76401a2015-04-24 14:12:15 -0700759__attribute__ ((visibility ("default")))
760bool audio_hw_send_gain_dep_calibration(int level) {
761 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700762 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700763
764 pthread_mutex_lock(&adev_init_lock);
765
766 if (adev != NULL && adev->platform != NULL) {
767 pthread_mutex_lock(&adev->lock);
768 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530770 // cache level info for any of the use case which
771 // was not started.
772 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700773
vivek mehtaa76401a2015-04-24 14:12:15 -0700774 pthread_mutex_unlock(&adev->lock);
775 } else {
776 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
777 }
778
779 pthread_mutex_unlock(&adev_init_lock);
780
781 return ret_val;
782}
783
Ashish Jain5106d362016-05-11 19:23:33 +0530784static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
785{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800786 bool gapless_enabled = false;
787 const char *mixer_ctl_name = "Compress Gapless Playback";
788 struct mixer_ctl *ctl;
789
790 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700791 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530792
793 /*Disable gapless if its AV playback*/
794 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800795
796 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
797 if (!ctl) {
798 ALOGE("%s: Could not get ctl for mixer cmd - %s",
799 __func__, mixer_ctl_name);
800 return -EINVAL;
801 }
802
803 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
804 ALOGE("%s: Could not set gapless mode %d",
805 __func__, gapless_enabled);
806 return -EINVAL;
807 }
808 return 0;
809}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700810
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700811__attribute__ ((visibility ("default")))
812int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
813 int table_size) {
814 int ret_val = 0;
815 ALOGV("%s: enter ... ", __func__);
816
817 pthread_mutex_lock(&adev_init_lock);
818 if (adev == NULL) {
819 ALOGW("%s: adev is NULL .... ", __func__);
820 goto done;
821 }
822
823 pthread_mutex_lock(&adev->lock);
824 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
825 pthread_mutex_unlock(&adev->lock);
826done:
827 pthread_mutex_unlock(&adev_init_lock);
828 ALOGV("%s: exit ... ", __func__);
829 return ret_val;
830}
831
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800832bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800833{
834 bool ret = false;
835 ALOGV("%s: enter ...", __func__);
836
837 pthread_mutex_lock(&adev_init_lock);
838
839 if (adev != NULL && adev->platform != NULL) {
840 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800841 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800842 pthread_mutex_unlock(&adev->lock);
843 }
844
845 pthread_mutex_unlock(&adev_init_lock);
846
847 ALOGV("%s: exit with ret %d", __func__, ret);
848 return ret;
849}
Aalique Grahame22e49102018-12-18 14:23:57 -0800850
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700851static bool is_supported_format(audio_format_t format)
852{
Eric Laurent86e17132013-09-12 17:49:30 -0700853 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530854 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530855 format == AUDIO_FORMAT_AAC_LC ||
856 format == AUDIO_FORMAT_AAC_HE_V1 ||
857 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530858 format == AUDIO_FORMAT_AAC_ADTS_LC ||
859 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530861 format == AUDIO_FORMAT_AAC_LATM_LC ||
862 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530864 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
865 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530866 format == AUDIO_FORMAT_PCM_FLOAT ||
867 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700868 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530869 format == AUDIO_FORMAT_AC3 ||
870 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700871 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530872 format == AUDIO_FORMAT_DTS ||
873 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800874 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530875 format == AUDIO_FORMAT_ALAC ||
876 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530877 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530878 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800879 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530880 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700881 format == AUDIO_FORMAT_APTX ||
882 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800883 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700884
885 return false;
886}
887
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888static inline bool is_mmap_usecase(audio_usecase_t uc_id)
889{
890 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800891 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700892 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
893}
894
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700895static inline bool is_valid_volume(float left, float right)
896{
897 return ((left >= 0.0f && right >= 0.0f) ? true : false);
898}
899
Avinash Vaish71a8b972014-07-24 15:36:33 +0530900static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
901 struct audio_usecase *uc_info)
902{
903 struct listnode *node;
904 struct audio_usecase *usecase;
905
906 if (uc_info == NULL)
907 return -EINVAL;
908
909 /* Re-route all voice usecases on the shared backend other than the
910 specified usecase to new snd devices */
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800913 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530914 enable_audio_route(adev, usecase);
915 }
916 return 0;
917}
918
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530919static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530920{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530921 ALOGV("%s", __func__);
922 audio_route_apply_and_update_path(adev->audio_route,
923 "asrc-mode");
924 adev->asrc_mode_enabled = true;
925}
926
927static void disable_asrc_mode(struct audio_device *adev)
928{
929 ALOGV("%s", __func__);
930 audio_route_reset_and_update_path(adev->audio_route,
931 "asrc-mode");
932 adev->asrc_mode_enabled = false;
933}
934
935/*
936 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
937 * 44.1 or Native DSD backends are enabled for any of current use case.
938 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
939 * - Disable current mix path use case(Headphone backend) and re-enable it with
940 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
941 * e.g. Naitve DSD or Headphone 44.1 -> + 48
942 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530943static void check_and_set_asrc_mode(struct audio_device *adev,
944 struct audio_usecase *uc_info,
945 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530946{
947 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530948 int i, num_new_devices = 0;
949 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
950 /*
951 *Split snd device for new combo use case
952 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
953 */
954 if (platform_split_snd_device(adev->platform,
955 snd_device,
956 &num_new_devices,
957 split_new_snd_devices) == 0) {
958 for (i = 0; i < num_new_devices; i++)
959 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
960 } else {
961 int new_backend_idx = platform_get_backend_index(snd_device);
962 if (((new_backend_idx == HEADPHONE_BACKEND) ||
963 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
964 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
965 !adev->asrc_mode_enabled) {
966 struct listnode *node = NULL;
967 struct audio_usecase *uc = NULL;
968 struct stream_out *curr_out = NULL;
969 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
970 int i, num_devices, ret = 0;
971 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530972
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530973 list_for_each(node, &adev->usecase_list) {
974 uc = node_to_item(node, struct audio_usecase, list);
975 curr_out = (struct stream_out*) uc->stream.out;
976 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
977 /*
978 *Split snd device for existing combo use case
979 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
980 */
981 ret = platform_split_snd_device(adev->platform,
982 uc->out_snd_device,
983 &num_devices,
984 split_snd_devices);
985 if (ret < 0 || num_devices == 0) {
986 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
987 split_snd_devices[0] = uc->out_snd_device;
988 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800989 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530990 for (i = 0; i < num_devices; i++) {
991 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
992 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
993 if((new_backend_idx == HEADPHONE_BACKEND) &&
994 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
995 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
996 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
997 __func__);
998 enable_asrc_mode(adev);
999 break;
1000 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1001 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1002 (usecase_backend_idx == HEADPHONE_BACKEND)) {
1003 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1004 __func__);
1005 disable_audio_route(adev, uc);
1006 disable_snd_device(adev, uc->out_snd_device);
1007 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1008 if (new_backend_idx == DSD_NATIVE_BACKEND)
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-true-highquality-mode");
1011 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1012 (curr_out->bit_width >= 24))
1013 audio_route_apply_and_update_path(adev->audio_route,
1014 "hph-highquality-mode");
1015 enable_asrc_mode(adev);
1016 enable_snd_device(adev, uc->out_snd_device);
1017 enable_audio_route(adev, uc);
1018 break;
1019 }
1020 }
1021 // reset split devices count
1022 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001023 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301024 if (adev->asrc_mode_enabled)
1025 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301026 }
1027 }
1028 }
1029}
1030
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1032 struct audio_effect_config effect_config,
1033 unsigned int param_value)
1034{
1035 char mixer_ctl_name[] = "Audio Effect";
1036 struct mixer_ctl *ctl;
1037 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001038 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001039
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001040 if (in == NULL) {
1041 ALOGE("%s: active input stream is NULL", __func__);
1042 return -EINVAL;
1043 }
1044
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001045 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1046 if (!ctl) {
1047 ALOGE("%s: Could not get mixer ctl - %s",
1048 __func__, mixer_ctl_name);
1049 return -EINVAL;
1050 }
1051
1052 set_values[0] = 1; //0:Rx 1:Tx
1053 set_values[1] = in->app_type_cfg.app_type;
1054 set_values[2] = (long)effect_config.module_id;
1055 set_values[3] = (long)effect_config.instance_id;
1056 set_values[4] = (long)effect_config.param_id;
1057 set_values[5] = param_value;
1058
1059 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1060
1061 return 0;
1062
1063}
1064
1065static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1066 int effect_type, unsigned int *param_value)
1067{
1068 int ret = 0;
1069 struct audio_effect_config other_effect_config;
1070 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001071 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001072
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001073 if (in == NULL) {
1074 ALOGE("%s: active input stream is NULL", __func__);
1075 return -EINVAL;
1076 }
1077
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001078 usecase = get_usecase_from_list(adev, in->usecase);
1079 if (!usecase)
1080 return -EINVAL;
1081
1082 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1083 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1084 if (ret < 0) {
1085 ALOGE("%s Failed to get effect params %d", __func__, ret);
1086 return ret;
1087 }
1088
1089 if (module_id == other_effect_config.module_id) {
1090 //Same module id for AEC/NS. Values need to be combined
1091 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1092 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1093 *param_value |= other_effect_config.param_value;
1094 }
1095 }
1096
1097 return ret;
1098}
1099
1100static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301101{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 struct audio_effect_config effect_config;
1103 struct audio_usecase *usecase = NULL;
1104 int ret = 0;
1105 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001106 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001108 if(!voice_extn_is_dynamic_ecns_enabled())
1109 return ENOSYS;
1110
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001111 if (!in) {
1112 ALOGE("%s: Invalid input stream", __func__);
1113 return -EINVAL;
1114 }
1115
1116 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1117
1118 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001119 if (usecase == NULL) {
1120 ALOGE("%s: Could not find the usecase (%d) in the list",
1121 __func__, in->usecase);
1122 return -EINVAL;
1123 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001124
1125 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1126 if (ret < 0) {
1127 ALOGE("%s Failed to get module id %d", __func__, ret);
1128 return ret;
1129 }
1130 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1131 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1132
1133 if(enable)
1134 param_value = effect_config.param_value;
1135
1136 /*Special handling for AEC & NS effects Param values need to be
1137 updated if module ids are same*/
1138
1139 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1140 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1141 if (ret < 0)
1142 return ret;
1143 }
1144
1145 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1146
1147 return ret;
1148}
1149
1150static void check_and_enable_effect(struct audio_device *adev)
1151{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001152 if(!voice_extn_is_dynamic_ecns_enabled())
1153 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001154
Eric Laurent637e2d42018-11-15 12:24:31 -08001155 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156
Eric Laurent637e2d42018-11-15 12:24:31 -08001157 if (in != NULL && !in->standby) {
1158 if (in->enable_aec)
1159 enable_disable_effect(adev, EFFECT_AEC, true);
1160
1161 if (in->enable_ns &&
1162 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1163 enable_disable_effect(adev, EFFECT_NS, true);
1164 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001165 }
1166}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001167
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001168int pcm_ioctl(struct pcm *pcm, int request, ...)
1169{
1170 va_list ap;
1171 void * arg;
1172 int pcm_fd = *(int*)pcm;
1173
1174 va_start(ap, request);
1175 arg = va_arg(ap, void *);
1176 va_end(ap);
1177
1178 return ioctl(pcm_fd, request, arg);
1179}
1180
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001181int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001182 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001185 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301186 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301187 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001188 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301189 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001190
1191 if (usecase == NULL)
1192 return -EINVAL;
1193
1194 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1195
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 if (usecase->type == PCM_CAPTURE) {
1197 struct stream_in *in = usecase->stream.in;
1198 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001200
1201 if (in) {
1202 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001203 list_init(&out_devices);
1204 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001205 struct listnode *node;
1206 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1207 USECASE_AUDIO_PLAYBACK_VOIP);
1208 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else if (adev->primary_output &&
1212 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001213 assign_devices(&out_devices,
1214 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001215 } else {
1216 list_for_each(node, &adev->usecase_list) {
1217 uinfo = node_to_item(node, struct audio_usecase, list);
1218 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001219 assign_devices(&out_devices,
1220 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001221 break;
1222 }
1223 }
1224 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001225
1226 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 in->ec_opened = true;
1228 }
1229 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001230 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1231 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1232 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001233 snd_device = usecase->in_snd_device;
1234 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001235 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001237
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001238#ifdef DS1_DOLBY_DAP_ENABLED
1239 audio_extn_dolby_set_dmid(adev);
1240 audio_extn_dolby_set_endpoint(adev);
1241#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001242 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001243 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301244 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001245 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001246 if (audio_extn_is_maxx_audio_enabled())
1247 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301248 audio_extn_utils_send_audio_calibration(adev, usecase);
Weiyin Jiangaf20db92020-11-09 14:08:59 +08001249 if ((usecase->type == PCM_PLAYBACK) &&
1250 ((out = usecase->stream.out) != NULL)) {
1251 if (!is_offload_usecase(out->usecase)) {
1252 pthread_mutex_lock(&out->latch_lock);
1253 out->muted = false;
1254 pthread_mutex_unlock(&out->latch_lock);
1255 } else if (out->compr) {
Manish Dewangan58229382017-02-02 15:48:41 +05301256 audio_extn_utils_compress_set_clk_rec_mode(usecase);
Weiyin Jiangaf20db92020-11-09 14:08:59 +08001257 }
Manish Dewangan58229382017-02-02 15:48:41 +05301258 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301259
1260 if (usecase->type == PCM_CAPTURE) {
1261 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001262 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301263 ALOGD("%s: set custom mtmx params v1", __func__);
1264 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1265 }
1266 } else {
1267 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1268 }
Manish Dewangan58229382017-02-02 15:48:41 +05301269
Andy Hung756ecc12018-10-19 17:47:12 -07001270 // we shouldn't truncate mixer_path
1271 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1272 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1273 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001274 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001275 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301276 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1277 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1278 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1279 if (parms) {
1280 audio_extn_fm_set_parameters(adev, parms);
1281 str_parms_destroy(parms);
1282 }
1283 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284 ALOGV("%s: exit", __func__);
1285 return 0;
1286}
1287
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001288int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001289 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001292 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301293 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001294
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301295 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001296 return -EINVAL;
1297
1298 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301299 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001300 snd_device = usecase->in_snd_device;
1301 else
1302 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001303
1304 /* disable island and power mode on supported device for voice call */
1305 if (usecase->type == VOICE_CALL) {
1306 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1307 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1308 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1309 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1310 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1311 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1312 ALOGD("%s: disable island cfg and power mode in voice tx path",
1313 __func__);
1314 }
1315 }
1316 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1317 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1318 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1319 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1320 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1321 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1322 ALOGD("%s: disable island cfg and power mode in voice rx path",
1323 __func__);
1324 }
1325 }
1326 }
1327
Andy Hung756ecc12018-10-19 17:47:12 -07001328 // we shouldn't truncate mixer_path
1329 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1330 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1331 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001332 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001333 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001334 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001335 if (usecase->type == PCM_CAPTURE) {
1336 struct stream_in *in = usecase->stream.in;
1337 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001338 struct listnode out_devices;
1339 list_init(&out_devices);
1340 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001341 in->ec_opened = false;
1342 }
1343 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001344 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301345 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301346
1347 if (usecase->type == PCM_CAPTURE) {
1348 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001349 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301350 ALOGD("%s: reset custom mtmx params v1", __func__);
1351 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1352 }
1353 } else {
1354 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1355 }
1356
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001357 if ((usecase->type == PCM_PLAYBACK) &&
1358 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301359 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361 ALOGV("%s: exit", __func__);
1362 return 0;
1363}
1364
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001365int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001366 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301368 int i, num_devices = 0;
1369 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1371
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001372 if (snd_device < SND_DEVICE_MIN ||
1373 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001374 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001375 return -EINVAL;
1376 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001378 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001379 ALOGE("%s: Invalid sound device returned", __func__);
1380 return -EINVAL;
1381 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001382
1383 adev->snd_dev_ref_cnt[snd_device]++;
1384
1385 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1386 (platform_split_snd_device(adev->platform,
1387 snd_device,
1388 &num_devices,
1389 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001390 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001391 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001392 /* Set backend config for A2DP to ensure slimbus configuration
1393 is correct if A2DP is already active and backend is closed
1394 and re-opened */
1395 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1396 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 return 0;
1398 }
1399
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001400 if (audio_extn_spkr_prot_is_enabled())
1401 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001402
Aalique Grahame22e49102018-12-18 14:23:57 -08001403 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1404
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001405 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1406 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001407 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1408 goto err;
1409 }
1410 audio_extn_dev_arbi_acquire(snd_device);
1411 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001412 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001413 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001414 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001415 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001416 } else if (platform_split_snd_device(adev->platform,
1417 snd_device,
1418 &num_devices,
1419 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301420 for (i = 0; i < num_devices; i++) {
1421 enable_snd_device(adev, new_snd_devices[i]);
1422 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001423 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001424 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001425 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301426
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001427 /* enable island and power mode on supported device */
1428 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1429 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1430 platform_set_island_cfg_on_device(adev, snd_device, true);
1431 platform_set_power_mode_on_device(adev, snd_device, true);
1432 ALOGD("%s: enable island cfg and power mode on: %s",
1433 __func__, device_name);
1434 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301435
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301436 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1437 if (audio_extn_a2dp_start_playback() < 0) {
1438 ALOGE(" fail to configure A2dp Source control path ");
1439 goto err;
1440 } else {
1441 adev->a2dp_started = true;
1442 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001443 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001444
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001445 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1446 (audio_extn_a2dp_start_capture() < 0)) {
1447 ALOGE(" fail to configure A2dp Sink control path ");
1448 goto err;
1449 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301450
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001451 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1452 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1453 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1454 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1455 ALOGE(" fail to configure sco control path ");
1456 goto err;
1457 }
Zhou Song12c29502019-03-16 10:37:18 +08001458 }
1459
Zhou Song331c8e52019-08-26 14:16:12 +08001460 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001461 /* due to the possibility of calibration overwrite between listen
1462 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001463 audio_extn_sound_trigger_update_device_status(snd_device,
1464 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301465 audio_extn_listen_update_device_status(snd_device,
1466 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001467 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001468 audio_extn_sound_trigger_update_device_status(snd_device,
1469 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301470 audio_extn_listen_update_device_status(snd_device,
1471 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001472 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001473 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001474 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001475 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301476
1477 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1478 !adev->native_playback_enabled &&
1479 audio_is_true_native_stream_active(adev)) {
1480 ALOGD("%s: %d: napb: enabling native mode in hardware",
1481 __func__, __LINE__);
1482 audio_route_apply_and_update_path(adev->audio_route,
1483 "true-native-mode");
1484 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301485 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301486 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1487 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001488 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001489 ALOGD("%s: init ec ref loopback", __func__);
1490 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494err:
1495 adev->snd_dev_ref_cnt[snd_device]--;
1496 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497}
1498
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001499int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001500 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301502 int i, num_devices = 0;
1503 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001504 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1505
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001506 if (snd_device < SND_DEVICE_MIN ||
1507 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001508 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001509 return -EINVAL;
1510 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001511
1512 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1513 ALOGE("%s: Invalid sound device returned", __func__);
1514 return -EINVAL;
1515 }
1516
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1518 ALOGE("%s: device ref cnt is already 0", __func__);
1519 return -EINVAL;
1520 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001521
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001522 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001523
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001524
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001526 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301527
Aalique Grahame22e49102018-12-18 14:23:57 -08001528 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1529
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001530 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1531 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001532 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001533
1534 // when speaker device is disabled, reset swap.
1535 // will be renabled on usecase start
1536 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001537 } else if (platform_split_snd_device(adev->platform,
1538 snd_device,
1539 &num_devices,
1540 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301541 for (i = 0; i < num_devices; i++) {
1542 disable_snd_device(adev, new_snd_devices[i]);
1543 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001544 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001545 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001546 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001547 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001548
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301549 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301550 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301551 adev->a2dp_started = false;
1552 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001553 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001554 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001555 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301556 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001557 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301558 adev->native_playback_enabled) {
1559 ALOGD("%s: %d: napb: disabling native mode in hardware",
1560 __func__, __LINE__);
1561 audio_route_reset_and_update_path(adev->audio_route,
1562 "true-native-mode");
1563 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001564 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301565 adev->asrc_mode_enabled) {
1566 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301567 disable_asrc_mode(adev);
1568 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001569 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301570 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001571 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001572 ALOGD("%s: deinit ec ref loopback", __func__);
1573 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1574 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001575
1576 audio_extn_utils_release_snd_device(snd_device);
1577 } else {
1578 if (platform_split_snd_device(adev->platform,
1579 snd_device,
1580 &num_devices,
1581 new_snd_devices) == 0) {
1582 for (i = 0; i < num_devices; i++) {
1583 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1584 }
1585 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001586 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588 return 0;
1589}
1590
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001591/*
1592 legend:
1593 uc - existing usecase
1594 new_uc - new usecase
1595 d1, d11, d2 - SND_DEVICE enums
1596 a1, a2 - corresponding ANDROID device enums
1597 B1, B2 - backend strings
1598
1599case 1
1600 uc->dev d1 (a1) B1
1601 new_uc->dev d1 (a1), d2 (a2) B1, B2
1602
1603 resolution: disable and enable uc->dev on d1
1604
1605case 2
1606 uc->dev d1 (a1) B1
1607 new_uc->dev d11 (a1) B1
1608
1609 resolution: need to switch uc since d1 and d11 are related
1610 (e.g. speaker and voice-speaker)
1611 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1612
1613case 3
1614 uc->dev d1 (a1) B1
1615 new_uc->dev d2 (a2) B2
1616
1617 resolution: no need to switch uc
1618
1619case 4
1620 uc->dev d1 (a1) B1
1621 new_uc->dev d2 (a2) B1
1622
1623 resolution: disable enable uc-dev on d2 since backends match
1624 we cannot enable two streams on two different devices if they
1625 share the same backend. e.g. if offload is on speaker device using
1626 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1627 using the same backend, offload must also be switched to voice-handset.
1628
1629case 5
1630 uc->dev d1 (a1) B1
1631 new_uc->dev d1 (a1), d2 (a2) B1
1632
1633 resolution: disable enable uc-dev on d2 since backends match
1634 we cannot enable two streams on two different devices if they
1635 share the same backend.
1636
1637case 6
1638 uc->dev d1 (a1) B1
1639 new_uc->dev d2 (a1) B2
1640
1641 resolution: no need to switch
1642
1643case 7
1644 uc->dev d1 (a1), d2 (a2) B1, B2
1645 new_uc->dev d1 (a1) B1
1646
1647 resolution: no need to switch
1648
Zhou Song4ba65882018-07-09 14:48:07 +08001649case 8
1650 uc->dev d1 (a1) B1
1651 new_uc->dev d11 (a1), d2 (a2) B1, B2
1652 resolution: compared to case 1, for this case, d1 and d11 are related
1653 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301654
1655case 9
1656 uc->dev d1 (a1), d2(a2) B1 B2
1657 new_uc->dev d1 (a1), d22 (a2) B1, B2
1658 resolution: disable enable uc-dev on d2 since backends match
1659 we cannot enable two streams on two different devices if they
1660 share the same backend. This is special case for combo use case
1661 with a2dp and sco devices which uses same backend.
1662 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001663*/
1664static snd_device_t derive_playback_snd_device(void * platform,
1665 struct audio_usecase *uc,
1666 struct audio_usecase *new_uc,
1667 snd_device_t new_snd_device)
1668{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001669 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001670
1671 snd_device_t d1 = uc->out_snd_device;
1672 snd_device_t d2 = new_snd_device;
1673
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001674 list_init(&a1);
1675 list_init(&a2);
1676
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301677 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301678 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001679 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1680 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301681 break;
1682 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001683 assign_devices(&a1, &uc->stream.out->device_list);
1684 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301685 break;
1686 }
1687
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001688 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001689 if (!compare_devices(&a1, &a2) &&
1690 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001691 snd_device_t d3[2];
1692 int num_devices = 0;
1693 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001694 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001695 &num_devices,
1696 d3);
1697 if (ret < 0) {
1698 if (ret != -ENOSYS) {
1699 ALOGW("%s failed to split snd_device %d",
1700 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001701 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001702 }
1703 goto end;
1704 }
1705
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001706 if (platform_check_backends_match(d3[0], d3[1])) {
1707 return d2; // case 5
1708 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301709 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1710 platform_check_backends_match(d1, d2))
1711 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001712 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301713 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001714 // check if d1 is related to any of d3's
1715 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001716 return d1; // case 1
1717 else
1718 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001719 }
1720 } else {
1721 if (platform_check_backends_match(d1, d2)) {
1722 return d2; // case 2, 4
1723 } else {
1724 return d1; // case 6, 3
1725 }
1726 }
1727
1728end:
1729 return d2; // return whatever was calculated before.
1730}
1731
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001732static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301733 struct audio_usecase *uc_info,
1734 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001735{
1736 struct listnode *node;
1737 struct audio_usecase *usecase;
1738 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301739 snd_device_t uc_derive_snd_device;
1740 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001741 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1742 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001743 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301744 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 /*
1746 * This function is to make sure that all the usecases that are active on
1747 * the hardware codec backend are always routed to any one device that is
1748 * handled by the hardware codec.
1749 * For example, if low-latency and deep-buffer usecases are currently active
1750 * on speaker and out_set_parameters(headset) is received on low-latency
1751 * output, then we have to make sure deep-buffer is also switched to headset,
1752 * because of the limitation that both the devices cannot be enabled
1753 * at the same time as they share the same backend.
1754 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001755 /*
1756 * This call is to check if we need to force routing for a particular stream
1757 * If there is a backend configuration change for the device when a
1758 * new stream starts, then ADM needs to be closed and re-opened with the new
1759 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001760 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001761 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001762 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1763 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301764 /* For a2dp device reconfigure all active sessions
1765 * with new AFE encoder format based on a2dp state
1766 */
1767 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301768 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1769 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301770 audio_extn_a2dp_is_force_device_switch()) {
1771 force_routing = true;
1772 force_restart_session = true;
1773 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001774
1775 /*
1776 * Island cfg and power mode config needs to set before AFE port start.
1777 * Set force routing in case of voice device was enable before.
1778 */
1779 if (uc_info->type == VOICE_CALL &&
1780 voice_extn_is_voice_power_mode_supported() &&
1781 platform_check_and_update_island_power_status(adev->platform,
1782 uc_info,
1783 snd_device)) {
1784 force_routing = true;
1785 ALOGD("%s:becf: force routing %d for power mode supported device",
1786 __func__, force_routing);
1787 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301788 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1789
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001790 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001791 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001792 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001793 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1794 switch_device[i] = false;
1795
1796 list_for_each(node, &adev->usecase_list) {
1797 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001798
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301799 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1800 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301801 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301802 platform_get_snd_device_name(usecase->out_snd_device),
1803 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301804 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1805 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301806 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1807 usecase, uc_info, snd_device);
1808 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001809 (is_codec_backend_out_device_type(&usecase->device_list) ||
1810 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1811 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1812 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1813 is_a2dp_out_device_type(&usecase->device_list) ||
1814 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301815 ((force_restart_session) ||
1816 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301817 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1818 __func__, use_case_table[usecase->id],
1819 platform_get_snd_device_name(usecase->out_snd_device));
1820 disable_audio_route(adev, usecase);
1821 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301822 /* Enable existing usecase on derived playback device */
1823 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301824 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826 }
1827 }
1828
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301829 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1830 num_uc_to_switch);
1831
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001833 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301835 /* Make sure the previous devices to be disabled first and then enable the
1836 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001840 /* Check if output sound device to be switched can be split and if any
1841 of the split devices match with derived sound device */
1842 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1843 &num_devices, split_snd_devices) == 0) {
1844 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1845 for (i = 0; i < num_devices; i++) {
1846 /* Disable devices that do not match with derived sound device */
1847 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1848 disable_snd_device(adev, split_snd_devices[i]);
1849 }
1850 } else {
1851 disable_snd_device(adev, usecase->out_snd_device);
1852 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001853 }
1854 }
1855
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001856 list_for_each(node, &adev->usecase_list) {
1857 usecase = node_to_item(node, struct audio_usecase, list);
1858 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001859 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1860 &num_devices, split_snd_devices) == 0) {
1861 /* Enable derived sound device only if it does not match with
1862 one of the split sound devices. This is because the matching
1863 sound device was not disabled */
1864 bool should_enable = true;
1865 for (i = 0; i < num_devices; i++) {
1866 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1867 should_enable = false;
1868 break;
1869 }
1870 }
1871 if (should_enable)
1872 enable_snd_device(adev, derive_snd_device[usecase->id]);
1873 } else {
1874 enable_snd_device(adev, derive_snd_device[usecase->id]);
1875 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001876 }
1877 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 /* Re-route all the usecases on the shared backend other than the
1880 specified usecase to new snd devices */
1881 list_for_each(node, &adev->usecase_list) {
1882 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301883 /* Update the out_snd_device only before enabling the audio route */
1884 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301885 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301886 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301887 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301888 use_case_table[usecase->id],
1889 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001890 /* Update voc calibration before enabling VoIP route */
1891 if (usecase->type == VOIP_CALL)
1892 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001893 usecase->out_snd_device,
1894 platform_get_input_snd_device(
1895 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301896 &uc_info->device_list,
1897 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301898 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301899 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001900 out_set_voip_volume(&usecase->stream.out->stream,
1901 usecase->stream.out->volume_l,
1902 usecase->stream.out->volume_r);
1903 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301904 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 }
1906 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 }
1908}
1909
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301910static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001911 struct audio_usecase *uc_info,
1912 snd_device_t snd_device)
1913{
1914 struct listnode *node;
1915 struct audio_usecase *usecase;
1916 bool switch_device[AUDIO_USECASE_MAX];
1917 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001918 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001919 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001920
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301921 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1922 snd_device);
1923 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301924
1925 /*
1926 * Make sure out devices is checked against out codec backend device and
1927 * also in devices against in codec backend. Checking out device against in
1928 * codec backend or vice versa causes issues.
1929 */
1930 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001931 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001932
1933 /*
1934 * Island cfg and power mode config needs to set before AFE port start.
1935 * Set force routing in case of voice device was enable before.
1936 */
1937
1938 if (uc_info->type == VOICE_CALL &&
1939 voice_extn_is_voice_power_mode_supported() &&
1940 platform_check_and_update_island_power_status(adev->platform,
1941 uc_info,
1942 snd_device)) {
1943 force_routing = true;
1944 ALOGD("%s:becf: force routing %d for power mode supported device",
1945 __func__, force_routing);
1946 }
1947
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001948 /*
1949 * This function is to make sure that all the active capture usecases
1950 * are always routed to the same input sound device.
1951 * For example, if audio-record and voice-call usecases are currently
1952 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1953 * is received for voice call then we have to make sure that audio-record
1954 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1955 * because of the limitation that two devices cannot be enabled
1956 * at the same time if they share the same backend.
1957 */
1958 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1959 switch_device[i] = false;
1960
1961 list_for_each(node, &adev->usecase_list) {
1962 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301963 /*
1964 * TODO: Enhance below condition to handle BT sco/USB multi recording
1965 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301966
1967 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1968 (usecase->in_snd_device != snd_device || force_routing));
1969 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1970 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1971 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001972 ((backend_check_cond &&
1973 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001974 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001975 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001976 is_single_device_type_equal(&usecase->device_list,
1977 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001978 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001979 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001980 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301981 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001982 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001983 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001984 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001985 switch_device[usecase->id] = true;
1986 num_uc_to_switch++;
1987 }
1988 }
1989
1990 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001991 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001992
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301993 /* Make sure the previous devices to be disabled first and then enable the
1994 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001995 list_for_each(node, &adev->usecase_list) {
1996 usecase = node_to_item(node, struct audio_usecase, list);
1997 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001998 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001999 }
2000 }
2001
2002 list_for_each(node, &adev->usecase_list) {
2003 usecase = node_to_item(node, struct audio_usecase, list);
2004 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002005 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002006 }
2007 }
2008
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002009 /* Re-route all the usecases on the shared backend other than the
2010 specified usecase to new snd devices */
2011 list_for_each(node, &adev->usecase_list) {
2012 usecase = node_to_item(node, struct audio_usecase, list);
2013 /* Update the in_snd_device only before enabling the audio route */
2014 if (switch_device[usecase->id] ) {
2015 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002016 if (usecase->type != VOICE_CALL) {
2017 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302018 if (usecase->type == VOIP_CALL) {
2019 snd_device_t voip_snd_device;
2020 voip_snd_device = platform_get_output_snd_device(adev->platform,
2021 uc_info->stream.out,
2022 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002023 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302024 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002025 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302026 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302027 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002028 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002029 }
2030 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002031 }
2032}
2033
Mingming Yin3a941d42016-02-17 18:08:05 -08002034static void reset_hdmi_sink_caps(struct stream_out *out) {
2035 int i = 0;
2036
2037 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2038 out->supported_channel_masks[i] = 0;
2039 }
2040 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2041 out->supported_formats[i] = 0;
2042 }
2043 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2044 out->supported_sample_rates[i] = 0;
2045 }
2046}
2047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002049static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050{
Mingming Yin3a941d42016-02-17 18:08:05 -08002051 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002052 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2053 out->extconn.cs.controller,
2054 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055
Mingming Yin3a941d42016-02-17 18:08:05 -08002056 reset_hdmi_sink_caps(out);
2057
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002058 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002059 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002060 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002061 out->extconn.cs.stream);
2062 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002063 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002064 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002065 }
2066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002069 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002070 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002071 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2072 case 6:
2073 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2074 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2075 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2076 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2077 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2078 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 break;
2080 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002081 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002082 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083 break;
2084 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002085
2086 // check channel format caps
2087 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002088 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2089 out->extconn.cs.controller,
2090 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002091 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2092 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2093 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2094 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2095 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2096 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2097 }
2098
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002099 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2100 out->extconn.cs.controller,
2101 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002102 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2103 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2104 }
2105
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002106 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2107 out->extconn.cs.controller,
2108 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002109 ALOGV(":%s HDMI supports DTS format", __func__);
2110 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2111 }
2112
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002113 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2114 out->extconn.cs.controller,
2115 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002116 ALOGV(":%s HDMI supports DTS HD format", __func__);
2117 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2118 }
2119
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002120 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2121 out->extconn.cs.controller,
2122 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002123 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2124 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2125 }
2126
Mingming Yin3a941d42016-02-17 18:08:05 -08002127
2128 // check sample rate caps
2129 i = 0;
2130 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002131 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2132 out->extconn.cs.controller,
2133 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002134 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2135 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2136 }
2137 }
2138
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002139 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140}
2141
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002142static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2143 uint32_t *supported_sample_rates __unused,
2144 uint32_t max_rates __unused)
2145{
2146 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2147 supported_sample_rates,
2148 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302149 ssize_t i = 0;
2150
2151 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002152 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2153 supported_sample_rates[i]);
2154 }
2155 return count;
2156}
2157
2158static inline int read_usb_sup_channel_masks(bool is_playback,
2159 audio_channel_mask_t *supported_channel_masks,
2160 uint32_t max_masks)
2161{
2162 int channels = audio_extn_usb_get_max_channels(is_playback);
2163 int channel_count;
2164 uint32_t num_masks = 0;
2165 if (channels > MAX_HIFI_CHANNEL_COUNT)
2166 channels = MAX_HIFI_CHANNEL_COUNT;
2167
2168 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002169 // start from 2 channels as framework currently doesn't support mono.
2170 if (channels >= FCC_2) {
2171 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2172 }
2173 for (channel_count = FCC_2;
2174 channel_count <= channels && num_masks < max_masks;
2175 ++channel_count) {
2176 supported_channel_masks[num_masks++] =
2177 audio_channel_mask_for_index_assignment_from_count(channel_count);
2178 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002179 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002180 // For capture we report all supported channel masks from 1 channel up.
2181 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002182 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2183 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002184 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2185 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2186 if (channel_count <= FCC_2) {
2187 mask = audio_channel_in_mask_from_count(channel_count);
2188 supported_channel_masks[num_masks++] = mask;
2189 }
2190 const audio_channel_mask_t index_mask =
2191 audio_channel_mask_for_index_assignment_from_count(channel_count);
2192 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2193 supported_channel_masks[num_masks++] = index_mask;
2194 }
2195 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002196 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302197
vincenttewf51c94e2019-05-07 10:28:53 +08002198 for (size_t i = 0; i < num_masks; ++i) {
2199 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2200 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302201 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002202 return num_masks;
2203}
2204
2205static inline int read_usb_sup_formats(bool is_playback __unused,
2206 audio_format_t *supported_formats,
2207 uint32_t max_formats __unused)
2208{
2209 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2210 switch (bitwidth) {
2211 case 24:
2212 // XXX : usb.c returns 24 for s24 and s24_le?
2213 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2214 break;
2215 case 32:
2216 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2217 break;
2218 case 16:
2219 default :
2220 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2221 break;
2222 }
2223 ALOGV("%s: %s supported format %d", __func__,
2224 is_playback ? "P" : "C", bitwidth);
2225 return 1;
2226}
2227
2228static inline int read_usb_sup_params_and_compare(bool is_playback,
2229 audio_format_t *format,
2230 audio_format_t *supported_formats,
2231 uint32_t max_formats,
2232 audio_channel_mask_t *mask,
2233 audio_channel_mask_t *supported_channel_masks,
2234 uint32_t max_masks,
2235 uint32_t *rate,
2236 uint32_t *supported_sample_rates,
2237 uint32_t max_rates) {
2238 int ret = 0;
2239 int num_formats;
2240 int num_masks;
2241 int num_rates;
2242 int i;
2243
2244 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2245 max_formats);
2246 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2247 max_masks);
2248
2249 num_rates = read_usb_sup_sample_rates(is_playback,
2250 supported_sample_rates, max_rates);
2251
2252#define LUT(table, len, what, dflt) \
2253 for (i=0; i<len && (table[i] != what); i++); \
2254 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2255
2256 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2257 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2258 LUT(supported_sample_rates, num_rates, *rate, 0);
2259
2260#undef LUT
2261 return ret < 0 ? -EINVAL : 0; // HACK TBD
2262}
2263
Alexy Josephb1379942016-01-29 15:49:38 -08002264audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002265 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002266{
2267 struct audio_usecase *usecase;
2268 struct listnode *node;
2269
2270 list_for_each(node, &adev->usecase_list) {
2271 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002272 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002273 ALOGV("%s: usecase id %d", __func__, usecase->id);
2274 return usecase->id;
2275 }
2276 }
2277 return USECASE_INVALID;
2278}
2279
Alexy Josephb1379942016-01-29 15:49:38 -08002280struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002281 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002282{
2283 struct audio_usecase *usecase;
2284 struct listnode *node;
2285
2286 list_for_each(node, &adev->usecase_list) {
2287 usecase = node_to_item(node, struct audio_usecase, list);
2288 if (usecase->id == uc_id)
2289 return usecase;
2290 }
2291 return NULL;
2292}
2293
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302294/*
2295 * is a true native playback active
2296 */
2297bool audio_is_true_native_stream_active(struct audio_device *adev)
2298{
2299 bool active = false;
2300 int i = 0;
2301 struct listnode *node;
2302
2303 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2304 ALOGV("%s:napb: not in true mode or non hdphones device",
2305 __func__);
2306 active = false;
2307 goto exit;
2308 }
2309
2310 list_for_each(node, &adev->usecase_list) {
2311 struct audio_usecase *uc;
2312 uc = node_to_item(node, struct audio_usecase, list);
2313 struct stream_out *curr_out =
2314 (struct stream_out*) uc->stream.out;
2315
2316 if (curr_out && PCM_PLAYBACK == uc->type) {
2317 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2318 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2319 uc->id, curr_out->sample_rate,
2320 curr_out->bit_width,
2321 platform_get_snd_device_name(uc->out_snd_device));
2322
2323 if (is_offload_usecase(uc->id) &&
2324 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2325 active = true;
2326 ALOGD("%s:napb:native stream detected", __func__);
2327 }
2328 }
2329 }
2330exit:
2331 return active;
2332}
2333
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002334uint32_t adev_get_dsp_bit_width_enforce_mode()
2335{
2336 if (adev == NULL) {
2337 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2338 return 0;
2339 }
2340 return adev->dsp_bit_width_enforce_mode;
2341}
2342
2343static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2344{
2345 char value[PROPERTY_VALUE_MAX];
2346 int trial;
2347 uint32_t dsp_bit_width_enforce_mode = 0;
2348
2349 if (!mixer) {
2350 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2351 __func__);
2352 return 0;
2353 }
2354
2355 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2356 value, NULL) > 0) {
2357 trial = atoi(value);
2358 switch (trial) {
2359 case 16:
2360 dsp_bit_width_enforce_mode = 16;
2361 break;
2362 case 24:
2363 dsp_bit_width_enforce_mode = 24;
2364 break;
2365 case 32:
2366 dsp_bit_width_enforce_mode = 32;
2367 break;
2368 default:
2369 dsp_bit_width_enforce_mode = 0;
2370 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2371 break;
2372 }
2373 }
2374
2375 return dsp_bit_width_enforce_mode;
2376}
2377
2378static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2379 uint32_t enforce_mode,
2380 bool enable)
2381{
2382 struct mixer_ctl *ctl = NULL;
2383 const char *mixer_ctl_name = "ASM Bit Width";
2384 uint32_t asm_bit_width_mode = 0;
2385
2386 if (enforce_mode == 0) {
2387 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2388 return;
2389 }
2390
2391 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2392 if (!ctl) {
2393 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2394 __func__, mixer_ctl_name);
2395 return;
2396 }
2397
2398 if (enable)
2399 asm_bit_width_mode = enforce_mode;
2400 else
2401 asm_bit_width_mode = 0;
2402
2403 ALOGV("%s DSP bit width feature status is %d width=%d",
2404 __func__, enable, asm_bit_width_mode);
2405 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2406 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2407 asm_bit_width_mode);
2408
2409 return;
2410}
2411
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302412/*
2413 * if native DSD playback active
2414 */
2415bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2416{
2417 bool active = false;
2418 struct listnode *node = NULL;
2419 struct audio_usecase *uc = NULL;
2420 struct stream_out *curr_out = NULL;
2421
2422 list_for_each(node, &adev->usecase_list) {
2423 uc = node_to_item(node, struct audio_usecase, list);
2424 curr_out = (struct stream_out*) uc->stream.out;
2425
2426 if (curr_out && PCM_PLAYBACK == uc->type &&
2427 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2428 active = true;
2429 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302430 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302431 }
2432 }
2433 return active;
2434}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302435
2436static bool force_device_switch(struct audio_usecase *usecase)
2437{
2438 bool ret = false;
2439 bool is_it_true_mode = false;
2440
Zhou Song30f2c3e2018-02-08 14:02:15 +08002441 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302442 usecase->type == TRANSCODE_LOOPBACK_RX ||
2443 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002444 return false;
2445 }
2446
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002447 if(usecase->stream.out == NULL) {
2448 ALOGE("%s: stream.out is NULL", __func__);
2449 return false;
2450 }
2451
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302452 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002453 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002454 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2455 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302456 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2457 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2458 (!is_it_true_mode && adev->native_playback_enabled)){
2459 ret = true;
2460 ALOGD("napb: time to toggle native mode");
2461 }
2462 }
2463
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302464 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302465 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2466 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002467 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302468 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302469 ALOGD("Force a2dp device switch to update new encoder config");
2470 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002471 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302472
Florian Pfister1a84f312018-07-19 14:38:18 +02002473 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302474 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2475 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002476 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302477 return ret;
2478}
2479
Aalique Grahame22e49102018-12-18 14:23:57 -08002480static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2481{
2482 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2483}
2484
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302485bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2486{
2487 bool ret=false;
2488 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002489 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2490 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302491 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2492 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002493 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302494 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002495 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2496 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302497 ret = true;
2498
2499 return ret;
2500}
2501
2502bool is_a2dp_device(snd_device_t out_snd_device)
2503{
2504 bool ret=false;
2505 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2506 ret = true;
2507
2508 return ret;
2509}
2510
2511bool is_bt_soc_on(struct audio_device *adev)
2512{
2513 struct mixer_ctl *ctl;
2514 char *mixer_ctl_name = "BT SOC status";
2515 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2516 bool bt_soc_status = true;
2517 if (!ctl) {
2518 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2519 __func__, mixer_ctl_name);
2520 /*This is to ensure we dont break targets which dont have the kernel change*/
2521 return true;
2522 }
2523 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2524 ALOGD("BT SOC status: %d",bt_soc_status);
2525 return bt_soc_status;
2526}
2527
Zhou Song331c8e52019-08-26 14:16:12 +08002528static int configure_btsco_sample_rate(snd_device_t snd_device)
2529{
2530 struct mixer_ctl *ctl = NULL;
2531 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2532 char *rate_str = NULL;
2533 bool is_rx_dev = true;
2534
2535 if (is_btsco_device(snd_device, snd_device)) {
2536 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2537 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2538 if (!ctl_sr_tx || !ctl_sr_rx) {
2539 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2540 if (!ctl_sr)
2541 return -ENOSYS;
2542 }
2543
2544 switch (snd_device) {
2545 case SND_DEVICE_OUT_BT_SCO:
2546 rate_str = "KHZ_8";
2547 break;
2548 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2549 case SND_DEVICE_IN_BT_SCO_MIC:
2550 rate_str = "KHZ_8";
2551 is_rx_dev = false;
2552 break;
2553 case SND_DEVICE_OUT_BT_SCO_WB:
2554 rate_str = "KHZ_16";
2555 break;
2556 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2557 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2558 rate_str = "KHZ_16";
2559 is_rx_dev = false;
2560 break;
2561 default:
2562 return 0;
2563 }
2564
2565 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2566 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2567 return -ENOSYS;
2568 }
2569 return 0;
2570}
2571
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302572int out_standby_l(struct audio_stream *stream);
2573
Eric Laurent637e2d42018-11-15 12:24:31 -08002574struct stream_in *adev_get_active_input(const struct audio_device *adev)
2575{
2576 struct listnode *node;
2577 struct stream_in *last_active_in = NULL;
2578
2579 /* Get last added active input.
2580 * TODO: We may use a priority mechanism to pick highest priority active source */
2581 list_for_each(node, &adev->usecase_list)
2582 {
2583 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2584 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2585 last_active_in = usecase->stream.in;
2586 }
2587
2588 return last_active_in;
2589}
2590
2591struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2592{
2593 struct listnode *node;
2594
2595 /* First check active inputs with voice communication source and then
2596 * any input if audio mode is in communication */
2597 list_for_each(node, &adev->usecase_list)
2598 {
2599 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2600 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2601 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2602 return usecase->stream.in;
2603 }
2604 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2605 return adev_get_active_input(adev);
2606
2607 return NULL;
2608}
2609
Carter Hsu2e429db2019-05-14 18:50:52 +08002610/*
2611 * Aligned with policy.h
2612 */
2613static inline int source_priority(int inputSource)
2614{
2615 switch (inputSource) {
2616 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2617 return 9;
2618 case AUDIO_SOURCE_CAMCORDER:
2619 return 8;
2620 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2621 return 7;
2622 case AUDIO_SOURCE_UNPROCESSED:
2623 return 6;
2624 case AUDIO_SOURCE_MIC:
2625 return 5;
2626 case AUDIO_SOURCE_ECHO_REFERENCE:
2627 return 4;
2628 case AUDIO_SOURCE_FM_TUNER:
2629 return 3;
2630 case AUDIO_SOURCE_VOICE_RECOGNITION:
2631 return 2;
2632 case AUDIO_SOURCE_HOTWORD:
2633 return 1;
2634 default:
2635 break;
2636 }
2637 return 0;
2638}
2639
2640static struct stream_in *get_priority_input(struct audio_device *adev)
2641{
2642 struct listnode *node;
2643 struct audio_usecase *usecase;
2644 int last_priority = 0, priority;
2645 struct stream_in *priority_in = NULL;
2646 struct stream_in *in;
2647
2648 list_for_each(node, &adev->usecase_list) {
2649 usecase = node_to_item(node, struct audio_usecase, list);
2650 if (usecase->type == PCM_CAPTURE) {
2651 in = usecase->stream.in;
2652 if (!in)
2653 continue;
2654 priority = source_priority(in->source);
2655
2656 if (priority > last_priority) {
2657 last_priority = priority;
2658 priority_in = in;
2659 }
2660 }
2661 }
2662 return priority_in;
2663}
2664
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002665int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002667 snd_device_t out_snd_device = SND_DEVICE_NONE;
2668 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002669 struct audio_usecase *usecase = NULL;
2670 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002671 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002672 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302673 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002674 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002675 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302677 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2678
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002679 usecase = get_usecase_from_list(adev, uc_id);
2680 if (usecase == NULL) {
2681 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2682 return -EINVAL;
2683 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002685 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002686 (usecase->type == VOIP_CALL) ||
2687 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302688 if(usecase->stream.out == NULL) {
2689 ALOGE("%s: stream.out is NULL", __func__);
2690 return -EINVAL;
2691 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002692 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002693 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2694 uc_id);
2695 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2696 uc_id);
2697 } else {
2698 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302699 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002700 in_snd_device = platform_get_input_snd_device(adev->platform,
2701 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302702 &usecase->stream.out->device_list,
2703 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002704 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002705 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302706 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302707 if (usecase->stream.inout == NULL) {
2708 ALOGE("%s: stream.inout is NULL", __func__);
2709 return -EINVAL;
2710 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002711 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302712 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2713 stream_out.format = usecase->stream.inout->out_config.format;
2714 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302715 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002716 assign_devices(&usecase->device_list,
2717 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302718 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2719 if (usecase->stream.inout == NULL) {
2720 ALOGE("%s: stream.inout is NULL", __func__);
2721 return -EINVAL;
2722 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302723 struct listnode out_devices;
2724 list_init(&out_devices);
2725 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2726 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002727 assign_devices(&usecase->device_list,
2728 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002729 } else {
2730 /*
2731 * If the voice call is active, use the sound devices of voice call usecase
2732 * so that it would not result any device switch. All the usecases will
2733 * be switched to new device when select_devices() is called for voice call
2734 * usecase. This is to avoid switching devices for voice call when
2735 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002736 * choose voice call device only if the use case device is
2737 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002738 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002739 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002740 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002741 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002742 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2743 is_codec_backend_out_device_type(&usecase->device_list)) ||
2744 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2745 is_codec_backend_in_device_type(&usecase->device_list)) ||
2746 is_single_device_type_equal(&vc_usecase->device_list,
2747 AUDIO_DEVICE_OUT_HEARING_AID) ||
2748 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002749 AUDIO_DEVICE_IN_VOICE_CALL) ||
2750 (is_single_device_type_equal(&usecase->device_list,
2751 AUDIO_DEVICE_IN_USB_HEADSET) &&
2752 is_single_device_type_equal(&vc_usecase->device_list,
2753 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002754 in_snd_device = vc_usecase->in_snd_device;
2755 out_snd_device = vc_usecase->out_snd_device;
2756 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002757 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002758 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002759 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002760 if ((voip_usecase != NULL) &&
2761 (usecase->type == PCM_PLAYBACK) &&
2762 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002763 out_snd_device_backend_match = platform_check_backends_match(
2764 voip_usecase->out_snd_device,
2765 platform_get_output_snd_device(
2766 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302767 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002768 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002769 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2770 (is_codec_backend_out_device_type(&usecase->device_list) ||
2771 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002772 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002773 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002774 in_snd_device = voip_usecase->in_snd_device;
2775 out_snd_device = voip_usecase->out_snd_device;
2776 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002777 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002778 hfp_ucid = audio_extn_hfp_get_usecase();
2779 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002780 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002781 in_snd_device = hfp_usecase->in_snd_device;
2782 out_snd_device = hfp_usecase->out_snd_device;
2783 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002784 }
2785 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302786 if (usecase->stream.out == NULL) {
2787 ALOGE("%s: stream.out is NULL", __func__);
2788 return -EINVAL;
2789 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002791 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002792 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002793 struct stream_out *voip_out = adev->primary_output;
2794 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002795 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002796 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2797 else
2798 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302799 usecase->stream.out,
2800 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002801 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002802
Eric Laurent637e2d42018-11-15 12:24:31 -08002803 if (voip_usecase)
2804 voip_out = voip_usecase->stream.out;
2805
2806 if (usecase->stream.out == voip_out && voip_in != NULL)
2807 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002808 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002809 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302810 if (usecase->stream.in == NULL) {
2811 ALOGE("%s: stream.in is NULL", __func__);
2812 return -EINVAL;
2813 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002815 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002816 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002817 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002818 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002819 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002820
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002821 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002822 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002823 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2824 USECASE_AUDIO_PLAYBACK_VOIP);
2825
Carter Hsu2e429db2019-05-14 18:50:52 +08002826 usecase->stream.in->enable_ec_port = false;
2827
Zhou Song62ea0282020-03-22 19:53:01 +08002828 bool is_ha_usecase = adev->ha_proxy_enable ?
2829 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2830 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2831 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002832 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002833 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002834 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002835 } else if (adev->primary_output &&
2836 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002837 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002838 } else {
2839 /* forcing speaker o/p device to get matching i/p pair
2840 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002841 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002842 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002843 priority_in = voip_in;
2844 } else {
2845 /* get the input with the highest priority source*/
2846 priority_in = get_priority_input(adev);
2847
2848 if (!priority_in)
2849 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002850 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002851
Eric Laurent637e2d42018-11-15 12:24:31 -08002852 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002853 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302854 &out_devices,
2855 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002857 }
2858 }
2859
2860 if (out_snd_device == usecase->out_snd_device &&
2861 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302862
2863 if (!force_device_switch(usecase))
2864 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 }
2866
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002867 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002868 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002869 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002870 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2871 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302872 }
2873
Aalique Grahame22e49102018-12-18 14:23:57 -08002874 if (out_snd_device != SND_DEVICE_NONE &&
2875 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2876 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2877 __func__,
2878 use_case_table[uc_id],
2879 adev->last_logged_snd_device[uc_id][0],
2880 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2881 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2882 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2883 -1,
2884 out_snd_device,
2885 platform_get_snd_device_name(out_snd_device),
2886 platform_get_snd_device_acdb_id(out_snd_device));
2887 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2888 }
2889 if (in_snd_device != SND_DEVICE_NONE &&
2890 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2891 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2892 __func__,
2893 use_case_table[uc_id],
2894 adev->last_logged_snd_device[uc_id][1],
2895 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2896 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2897 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2898 -1,
2899 in_snd_device,
2900 platform_get_snd_device_name(in_snd_device),
2901 platform_get_snd_device_acdb_id(in_snd_device));
2902 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2903 }
2904
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 /*
2907 * Limitation: While in call, to do a device switch we need to disable
2908 * and enable both RX and TX devices though one of them is same as current
2909 * device.
2910 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002911 if ((usecase->type == VOICE_CALL) &&
2912 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2913 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002914 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002915 }
2916
2917 if (((usecase->type == VOICE_CALL) ||
2918 (usecase->type == VOIP_CALL)) &&
2919 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2920 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302921 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002922 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002923 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002924
2925 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302926 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002927 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002928 }
2929
Aalique Grahame22e49102018-12-18 14:23:57 -08002930 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2931 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002932 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302933 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002934 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2935 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2936 else
2937 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302938 }
2939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002940 /* Disable current sound devices */
2941 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002942 disable_audio_route(adev, usecase);
2943 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 }
2945
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002946 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002947 disable_audio_route(adev, usecase);
2948 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 }
2950
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002951 /* Applicable only on the targets that has external modem.
2952 * New device information should be sent to modem before enabling
2953 * the devices to reduce in-call device switch time.
2954 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002955 if ((usecase->type == VOICE_CALL) &&
2956 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2957 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002958 status = platform_switch_voice_call_enable_device_config(adev->platform,
2959 out_snd_device,
2960 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002961 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002963 /* Enable new sound devices */
2964 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002965 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302966 if (platform_check_codec_asrc_support(adev->platform))
2967 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002968 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 }
2970
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002971 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302972 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002973 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002974 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002975
Avinash Vaish71a8b972014-07-24 15:36:33 +05302976 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002977 status = platform_switch_voice_call_device_post(adev->platform,
2978 out_snd_device,
2979 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302980 enable_audio_route_for_voice_usecases(adev, usecase);
2981 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002982
sangwoo170731f2013-06-08 15:36:36 +09002983 usecase->in_snd_device = in_snd_device;
2984 usecase->out_snd_device = out_snd_device;
2985
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302986 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2987 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302988 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002989 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002990 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002991 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2992 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2993 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2994 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2995 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2996 /*
2997 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2998 * configured device sample rate, if not update the COPP rate to be equal to the
2999 * device sample rate, else open COPP at stream sample rate
3000 */
3001 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3002 usecase->stream.out->sample_rate,
3003 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303004 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303005 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3006 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303007 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003008 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3009 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3010 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3011 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003012 }
3013 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003014
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003015 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003016
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003017 /* If input stream is already running then effect needs to be
3018 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003019 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003020 check_and_enable_effect(adev);
3021
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003022 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003023 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303024 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003025 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3026
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003027 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303028 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003029 voice_extn_compress_voip_is_started(adev))
3030 voice_set_sidetone(adev, out_snd_device, true);
3031 }
3032
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003033 /* Applicable only on the targets that has external modem.
3034 * Enable device command should be sent to modem only after
3035 * enabling voice call mixer controls
3036 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003037 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003038 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3039 out_snd_device,
3040 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303041
3042 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003043 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303044 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003045 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303046 if (is_bt_soc_on(adev) == false){
3047 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003048 if (in->pcm != NULL)
3049 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303050 }
3051 }
3052 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3053 && usecase->stream.out->started) {
3054 if (is_bt_soc_on(adev) == false) {
3055 ALOGD("BT SCO/A2DP disconnected while in connection");
3056 out_standby_l(&usecase->stream.out->stream.common);
3057 }
3058 }
3059 } else if ((usecase->stream.out != NULL) &&
3060 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303061 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3062 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003063 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303064 usecase->stream.out->started) {
3065 if (is_bt_soc_on(adev) == false) {
3066 ALOGD("BT SCO/A2dp disconnected while in connection");
3067 out_standby_l(&usecase->stream.out->stream.common);
3068 }
3069 }
3070 }
3071
Yung Ti Su70cb8242018-06-22 17:38:47 +08003072 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003073 struct stream_out *voip_out = voip_usecase->stream.out;
3074 audio_extn_utils_send_app_type_gain(adev,
3075 voip_out->app_type_cfg.app_type,
3076 &voip_out->app_type_cfg.gain[0]);
3077 }
3078
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303079 ALOGD("%s: done",__func__);
3080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 return status;
3082}
3083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084static int stop_input_stream(struct stream_in *in)
3085{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303086 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303088
3089 if (in == NULL) {
3090 ALOGE("%s: stream_in ptr is NULL", __func__);
3091 return -EINVAL;
3092 }
3093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003095 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096
Eric Laurent994a6932013-07-17 11:51:42 -07003097 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003098 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 uc_info = get_usecase_from_list(adev, in->usecase);
3100 if (uc_info == NULL) {
3101 ALOGE("%s: Could not find the usecase (%d) in the list",
3102 __func__, in->usecase);
3103 return -EINVAL;
3104 }
3105
Carter Hsu2e429db2019-05-14 18:50:52 +08003106 priority_in = get_priority_input(adev);
3107
Derek Chenea197282019-01-07 17:35:01 -08003108 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3109 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003110
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003111 /* Close in-call recording streams */
3112 voice_check_and_stop_incall_rec_usecase(adev, in);
3113
Eric Laurent150dbfe2013-02-27 14:31:02 -08003114 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003115 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003116
3117 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003118 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003120 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303121 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3122
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003123 list_remove(&uc_info->list);
3124 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125
Carter Hsu2e429db2019-05-14 18:50:52 +08003126 if (priority_in == in) {
3127 priority_in = get_priority_input(adev);
3128 if (priority_in)
3129 select_devices(adev, priority_in->usecase);
3130 }
3131
Vatsal Buchac09ae062018-11-14 13:25:08 +05303132 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003133 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 return ret;
3135}
3136
3137int start_input_stream(struct stream_in *in)
3138{
3139 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003140 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303142
3143 if (in == NULL) {
3144 ALOGE("%s: stream_in ptr is NULL", __func__);
3145 return -EINVAL;
3146 }
3147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003149 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003150 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151
Mingming Yin2664a5b2015-09-03 10:53:11 -07003152 if (get_usecase_from_list(adev, usecase) == NULL)
3153 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303154 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3155 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003156
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303157 if (CARD_STATUS_OFFLINE == in->card_status||
3158 CARD_STATUS_OFFLINE == adev->card_status) {
3159 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303160 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 goto error_config;
3162 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303163
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003164 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303165 if (!adev->bt_sco_on) {
3166 ALOGE("%s: SCO profile is not ready, return error", __func__);
3167 ret = -EIO;
3168 goto error_config;
3169 }
3170 }
3171
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003172 /* Check if source matches incall recording usecase criteria */
3173 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3174 if (ret)
3175 goto error_config;
3176 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003177 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3178
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303179 if (audio_extn_cin_attached_usecase(in))
3180 audio_extn_cin_acquire_usecase(in);
3181
Mingming Yin2664a5b2015-09-03 10:53:11 -07003182 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3183 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3184 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003185 ret = -EINVAL;
3186 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003187 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003188
Eric Laurentb23d5282013-05-14 15:27:20 -07003189 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 if (in->pcm_device_id < 0) {
3191 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3192 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003193 ret = -EINVAL;
3194 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003198
3199 if (!uc_info) {
3200 ret = -ENOMEM;
3201 goto error_config;
3202 }
3203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 uc_info->id = in->usecase;
3205 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003206 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003207 list_init(&uc_info->device_list);
3208 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003209 uc_info->in_snd_device = SND_DEVICE_NONE;
3210 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003212 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003213 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303214 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3215 adev->perf_lock_opts,
3216 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003217 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Derek Chenea197282019-01-07 17:35:01 -08003219 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3220 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003221
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303222 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3223
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303224 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303225 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303226 if (ret)
3227 goto error_open;
3228 else
3229 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003230 }
3231
Haynes Mathew George16081042017-05-31 17:16:49 -07003232 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003233 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003234 ALOGE("%s: pcm stream not ready", __func__);
3235 goto error_open;
3236 }
3237 ret = pcm_start(in->pcm);
3238 if (ret < 0) {
3239 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3240 goto error_open;
3241 }
3242 } else {
3243 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3244 unsigned int pcm_open_retry_count = 0;
3245
Zhou Song62ea0282020-03-22 19:53:01 +08003246 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3247 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003248 flags |= PCM_MMAP | PCM_NOIRQ;
3249 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3250 } else if (in->realtime) {
3251 flags |= PCM_MMAP | PCM_NOIRQ;
3252 }
3253
Garmond Leunge2433c32017-09-28 21:51:22 -07003254 if (audio_extn_ffv_get_stream() == in) {
3255 ALOGD("%s: ffv stream, update pcm config", __func__);
3256 audio_extn_ffv_update_pcm_config(&config);
3257 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003258 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3259 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3260
3261 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003262 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003263 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003264 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003265 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303266 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303267 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3268 adev->card_status = CARD_STATUS_OFFLINE;
3269 in->card_status = CARD_STATUS_OFFLINE;
3270 ret = -EIO;
3271 goto error_open;
3272 }
3273
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3275 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3276 if (in->pcm != NULL) {
3277 pcm_close(in->pcm);
3278 in->pcm = NULL;
3279 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003280 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003281 ret = -EIO;
3282 goto error_open;
3283 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003284 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003285 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3286 continue;
3287 }
3288 break;
3289 }
3290
3291 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003292 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003293 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003294 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003295 if (ret < 0) {
3296 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3297 pcm_close(in->pcm);
3298 in->pcm = NULL;
3299 goto error_open;
3300 }
3301 register_in_stream(in);
3302 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003303 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003304 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003305 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003306 if (ret < 0) {
3307 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003308 pcm_close(in->pcm);
3309 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003310 goto error_open;
3311 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003312 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003313 }
3314
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003315 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003316 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3317 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003318
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003319 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303320 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3321
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303322done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003323 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303324 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003325 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303326 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003327 return ret;
3328
3329error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003330 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303331 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003333
Eric Laurentc8400632013-02-14 19:04:54 -08003334error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003335 if (audio_extn_cin_attached_usecase(in))
3336 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303337 /*
3338 * sleep 50ms to allow sufficient time for kernel
3339 * drivers to recover incases like SSR.
3340 */
3341 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003342 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303343 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003347void lock_input_stream(struct stream_in *in)
3348{
3349 pthread_mutex_lock(&in->pre_lock);
3350 pthread_mutex_lock(&in->lock);
3351 pthread_mutex_unlock(&in->pre_lock);
3352}
3353
3354void lock_output_stream(struct stream_out *out)
3355{
3356 pthread_mutex_lock(&out->pre_lock);
3357 pthread_mutex_lock(&out->lock);
3358 pthread_mutex_unlock(&out->pre_lock);
3359}
3360
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003361/* must be called with out->lock locked */
3362static int send_offload_cmd_l(struct stream_out* out, int command)
3363{
3364 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3365
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003366 if (!cmd) {
3367 ALOGE("failed to allocate mem for command 0x%x", command);
3368 return -ENOMEM;
3369 }
3370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 ALOGVV("%s %d", __func__, command);
3372
3373 cmd->cmd = command;
3374 list_add_tail(&out->offload_cmd_list, &cmd->node);
3375 pthread_cond_signal(&out->offload_cond);
3376 return 0;
3377}
3378
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003379/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380static void stop_compressed_output_l(struct stream_out *out)
3381{
3382 out->offload_state = OFFLOAD_STATE_IDLE;
3383 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003384 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 if (out->compr != NULL) {
3386 compress_stop(out->compr);
3387 while (out->offload_thread_blocked) {
3388 pthread_cond_wait(&out->cond, &out->lock);
3389 }
3390 }
3391}
3392
Varun Balaraje49253e2017-07-06 19:48:56 +05303393bool is_interactive_usecase(audio_usecase_t uc_id)
3394{
3395 unsigned int i;
3396 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3397 if (uc_id == interactive_usecases[i])
3398 return true;
3399 }
3400 return false;
3401}
3402
3403static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3404{
3405 audio_usecase_t ret_uc = USECASE_INVALID;
3406 unsigned int intract_uc_index;
3407 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3408
3409 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3410 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3411 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3412 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3413 ret_uc = interactive_usecases[intract_uc_index];
3414 break;
3415 }
3416 }
3417
3418 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3419 return ret_uc;
3420}
3421
3422static void free_interactive_usecase(struct audio_device *adev,
3423 audio_usecase_t uc_id)
3424{
3425 unsigned int interact_uc_index;
3426 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3427
3428 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3429 if (interactive_usecases[interact_uc_index] == uc_id) {
3430 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3431 break;
3432 }
3433 }
3434 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3435}
3436
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003437bool is_offload_usecase(audio_usecase_t uc_id)
3438{
3439 unsigned int i;
3440 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3441 if (uc_id == offload_usecases[i])
3442 return true;
3443 }
3444 return false;
3445}
3446
Dhananjay Kumarac341582017-02-23 23:42:25 +05303447static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003448{
vivek mehta446c3962015-09-14 10:57:35 -07003449 audio_usecase_t ret_uc = USECASE_INVALID;
3450 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003451 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003452 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303453 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003454 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3455 else
3456 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003457
vivek mehta446c3962015-09-14 10:57:35 -07003458 pthread_mutex_lock(&adev->lock);
3459 if (get_usecase_from_list(adev, ret_uc) != NULL)
3460 ret_uc = USECASE_INVALID;
3461 pthread_mutex_unlock(&adev->lock);
3462
3463 return ret_uc;
3464 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003465
3466 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003467 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3468 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3469 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3470 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003471 break;
3472 }
3473 }
vivek mehta446c3962015-09-14 10:57:35 -07003474
3475 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3476 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003477}
3478
3479static void free_offload_usecase(struct audio_device *adev,
3480 audio_usecase_t uc_id)
3481{
vivek mehta446c3962015-09-14 10:57:35 -07003482 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003483 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003484
3485 if (!adev->multi_offload_enable)
3486 return;
3487
3488 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3489 if (offload_usecases[offload_uc_index] == uc_id) {
3490 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003491 break;
3492 }
3493 }
3494 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3495}
3496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497static void *offload_thread_loop(void *context)
3498{
3499 struct stream_out *out = (struct stream_out *) context;
3500 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003501 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003503 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003504 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3506
3507 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003508 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003509 out->offload_state = OFFLOAD_STATE_IDLE;
3510 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 for (;;) {
3512 struct offload_cmd *cmd = NULL;
3513 stream_callback_event_t event;
3514 bool send_callback = false;
3515
3516 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3517 __func__, list_empty(&out->offload_cmd_list),
3518 out->offload_state);
3519 if (list_empty(&out->offload_cmd_list)) {
3520 ALOGV("%s SLEEPING", __func__);
3521 pthread_cond_wait(&out->offload_cond, &out->lock);
3522 ALOGV("%s RUNNING", __func__);
3523 continue;
3524 }
3525
3526 item = list_head(&out->offload_cmd_list);
3527 cmd = node_to_item(item, struct offload_cmd, node);
3528 list_remove(item);
3529
3530 ALOGVV("%s STATE %d CMD %d out->compr %p",
3531 __func__, out->offload_state, cmd->cmd, out->compr);
3532
3533 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3534 free(cmd);
3535 break;
3536 }
3537
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003538 // allow OFFLOAD_CMD_ERROR reporting during standby
3539 // this is needed to handle failures during compress_open
3540 // Note however that on a pause timeout, the stream is closed
3541 // and no offload usecase will be active. Therefore this
3542 // special case is needed for compress_open failures alone
3543 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3544 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003545 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003546 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547 pthread_cond_signal(&out->cond);
3548 continue;
3549 }
3550 out->offload_thread_blocked = true;
3551 pthread_mutex_unlock(&out->lock);
3552 send_callback = false;
3553 switch(cmd->cmd) {
3554 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003555 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003557 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 send_callback = true;
3559 event = STREAM_CBK_EVENT_WRITE_READY;
3560 break;
3561 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003562 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303563 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003564 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303565 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003566 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303567 if (ret < 0)
3568 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303569 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303570 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003571 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003572 else
3573 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003574 if (-ENETRESET != ret && !(-EINTR == ret &&
3575 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303576 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303577 pthread_mutex_lock(&out->lock);
3578 out->send_new_metadata = 1;
3579 out->send_next_track_params = true;
3580 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303581 event = STREAM_CBK_EVENT_DRAIN_READY;
3582 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3583 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303584 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003585 break;
3586 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003587 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003588 ret = compress_drain(out->compr);
3589 ALOGD("copl(%p):out of compress_drain", out);
3590 // EINTR check avoids drain interruption due to SSR
3591 if (-ENETRESET != ret && !(-EINTR == ret &&
3592 CARD_STATUS_OFFLINE == out->card_status)) {
3593 send_callback = true;
3594 event = STREAM_CBK_EVENT_DRAIN_READY;
3595 } else
3596 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003597 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303598 case OFFLOAD_CMD_ERROR:
3599 ALOGD("copl(%p): sending error callback to AF", out);
3600 send_callback = true;
3601 event = STREAM_CBK_EVENT_ERROR;
3602 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603 default:
3604 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3605 break;
3606 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003607 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608 out->offload_thread_blocked = false;
3609 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003610 if (send_callback && out->client_callback) {
3611 ALOGVV("%s: sending client_callback event %d", __func__, event);
3612 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003613 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003614 free(cmd);
3615 }
3616
3617 pthread_cond_signal(&out->cond);
3618 while (!list_empty(&out->offload_cmd_list)) {
3619 item = list_head(&out->offload_cmd_list);
3620 list_remove(item);
3621 free(node_to_item(item, struct offload_cmd, node));
3622 }
3623 pthread_mutex_unlock(&out->lock);
3624
3625 return NULL;
3626}
3627
3628static int create_offload_callback_thread(struct stream_out *out)
3629{
3630 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3631 list_init(&out->offload_cmd_list);
3632 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3633 offload_thread_loop, out);
3634 return 0;
3635}
3636
3637static int destroy_offload_callback_thread(struct stream_out *out)
3638{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003639 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003640 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003641 stop_compressed_output_l(out);
3642 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3643
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003644 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645 pthread_mutex_unlock(&out->lock);
3646 pthread_join(out->offload_thread, (void **) NULL);
3647 pthread_cond_destroy(&out->offload_cond);
3648
3649 return 0;
3650}
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652static int stop_output_stream(struct stream_out *out)
3653{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303654 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 struct audio_usecase *uc_info;
3656 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003657 bool has_voip_usecase =
3658 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659
Eric Laurent994a6932013-07-17 11:51:42 -07003660 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003661 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 uc_info = get_usecase_from_list(adev, out->usecase);
3663 if (uc_info == NULL) {
3664 ALOGE("%s: Could not find the usecase (%d) in the list",
3665 __func__, out->usecase);
3666 return -EINVAL;
3667 }
3668
Derek Chenea197282019-01-07 17:35:01 -08003669 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3670 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003671
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003672 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303673 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003674 if (adev->visualizer_stop_output != NULL)
3675 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003676
3677 audio_extn_dts_remove_state_notifier_node(out->usecase);
3678
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003679 if (adev->offload_effects_stop_output != NULL)
3680 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003681 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3682 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3683 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003684 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003685
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003686 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3687 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003688 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003689 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003690
Eric Laurent150dbfe2013-02-27 14:31:02 -08003691 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003692 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003693
3694 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003695 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696
Aalique Grahame22e49102018-12-18 14:23:57 -08003697 audio_extn_extspk_update(adev->extspk);
3698
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003699 if (is_offload_usecase(out->usecase)) {
3700 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3701 adev->dsp_bit_width_enforce_mode,
3702 false);
3703 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003704 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003705 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3706 false);
3707
3708 if (ret != 0)
3709 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3710 /* default service interval was successfully updated,
3711 reopen USB backend with new service interval */
3712 ret = 0;
3713 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003714
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003715 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303716 out->started = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003717 pthread_mutex_lock(&out->latch_lock);
3718 out->muted = false;
3719 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003720 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303721 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003722 ALOGV("Disable passthrough , reset mixer to pcm");
3723 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003724#ifdef AUDIO_GKI_ENABLED
3725 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3726 out->compr_config.codec->reserved[0] = 0;
3727#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003728 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003729#endif
Mingming Yin21854652016-04-13 11:54:02 -07003730 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003731 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3732 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003733
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303734 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003735 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303736 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303737
Manish Dewangan21a850a2017-08-14 12:03:55 +05303738 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003739 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3740 if (ret < 0)
3741 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3742 }
3743
juyuchen2d415992018-11-16 14:15:16 +08003744 /* 1) media + voip output routing to handset must route media back to
3745 speaker when voip stops.
3746 2) trigger voip input to reroute when voip output changes to
3747 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003748 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003749 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003750 struct listnode *node;
3751 struct audio_usecase *usecase;
3752 list_for_each(node, &adev->usecase_list) {
3753 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003754 if ((usecase->type == PCM_CAPTURE &&
3755 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3756 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003757 continue;
3758
3759 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3760 __func__, usecase->id, use_case_table[usecase->id],
3761 out->usecase, use_case_table[out->usecase]);
3762 select_devices(adev, usecase->id);
3763 }
3764 }
3765
Garmond Leung5fd0b552018-04-17 11:56:12 -07003766 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003767 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 return ret;
3769}
3770
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003771struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3772 unsigned int flags, unsigned int pcm_open_retry_count,
3773 struct pcm_config *config)
3774{
3775 struct pcm* pcm = NULL;
3776
3777 while (1) {
3778 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3779 if (pcm == NULL || !pcm_is_ready(pcm)) {
3780 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3781 if (pcm != NULL) {
3782 pcm_close(pcm);
3783 pcm = NULL;
3784 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003785 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003786 return NULL;
3787
Weiyin Jiang72197252019-10-09 11:49:32 +08003788 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003789 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3790 continue;
3791 }
3792 break;
3793 }
3794
3795 if (pcm_is_ready(pcm)) {
3796 int ret = pcm_prepare(pcm);
3797 if (ret < 0) {
3798 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3799 pcm_close(pcm);
3800 pcm = NULL;
3801 }
3802 }
3803
3804 return pcm;
3805}
3806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807int start_output_stream(struct stream_out *out)
3808{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 struct audio_usecase *uc_info;
3811 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003812 char mixer_ctl_name[128];
3813 struct mixer_ctl *ctl = NULL;
3814 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303815 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003816 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Haynes Mathew George380745d2017-10-04 15:27:45 -07003818 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003819 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3820 ret = -EINVAL;
3821 goto error_config;
3822 }
3823
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003824 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303825 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003826 get_device_types(&out->device_list), is_haptic_usecase);
3827
3828 bool is_speaker_active = compare_device_type(&out->device_list,
3829 AUDIO_DEVICE_OUT_SPEAKER);
3830 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3831 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303832
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303833 if (CARD_STATUS_OFFLINE == out->card_status ||
3834 CARD_STATUS_OFFLINE == adev->card_status) {
3835 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303836 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003837 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303838 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303839
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003840 //Update incall music usecase to reflect correct voice session
3841 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3842 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3843 if (ret != 0) {
3844 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3845 __func__, ret);
3846 goto error_config;
3847 }
3848 }
3849
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003850 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003851 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003852 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303853 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303854 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303855 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3856 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3857 ret = -EAGAIN;
3858 goto error_config;
3859 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303860 }
3861 }
3862 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003863 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303864 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003865 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303866 //combo usecase just by pass a2dp
3867 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003868 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303869 } else {
3870 ALOGE("%s: SCO profile is not ready, return error", __func__);
3871 ret = -EAGAIN;
3872 goto error_config;
3873 }
3874 }
3875 }
3876
Eric Laurentb23d5282013-05-14 15:27:20 -07003877 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 if (out->pcm_device_id < 0) {
3879 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3880 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003881 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003882 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 }
3884
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003885 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003886 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3887 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003888 if (adev->haptic_pcm_device_id < 0) {
3889 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3890 __func__, adev->haptic_pcm_device_id, out->usecase);
3891 ret = -EINVAL;
3892 goto error_config;
3893 }
3894 }
3895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003897
3898 if (!uc_info) {
3899 ret = -ENOMEM;
3900 goto error_config;
3901 }
3902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 uc_info->id = out->usecase;
3904 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003905 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003906 list_init(&uc_info->device_list);
3907 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003908 uc_info->in_snd_device = SND_DEVICE_NONE;
3909 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003910
3911 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003912 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003913 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3914 /* USB backend is not reopened immediately.
3915 This is eventually done as part of select_devices */
3916 }
3917
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003918 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919
Wei Wangf7ca6c92017-11-21 14:51:20 -08003920 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303921 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3922 adev->perf_lock_opts,
3923 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303924
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003925 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303926 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303927 if (audio_extn_passthru_is_enabled() &&
3928 audio_extn_passthru_is_passthrough_stream(out)) {
3929 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303930 }
3931 }
3932
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003933 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003934 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303935 if (!a2dp_combo) {
3936 check_a2dp_restore_l(adev, out, false);
3937 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003938 struct listnode dev;
3939 list_init(&dev);
3940 assign_devices(&dev, &out->device_list);
3941 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3942 reassign_device_list(&out->device_list,
3943 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003944 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003945 reassign_device_list(&out->device_list,
3946 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303947 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003948 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303949 }
3950 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303951 select_devices(adev, out->usecase);
3952 if (is_a2dp_out_device_type(&out->device_list) &&
3953 !adev->a2dp_started) {
3954 if (is_speaker_active || is_speaker_safe_active) {
3955 struct listnode dev;
3956 list_init(&dev);
3957 assign_devices(&dev, &out->device_list);
3958 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3959 reassign_device_list(&out->device_list,
3960 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3961 else
3962 reassign_device_list(&out->device_list,
3963 AUDIO_DEVICE_OUT_SPEAKER, "");
3964 select_devices(adev, out->usecase);
3965 assign_devices(&out->device_list, &dev);
3966 } else {
3967 ret = -EINVAL;
3968 goto error_open;
3969 }
3970 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303971 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003972
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003973 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3974 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003975 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003976 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003977
Derek Chenea197282019-01-07 17:35:01 -08003978 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3979 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003980
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003981 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3982 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003983
3984 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003985 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003986 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3987 ALOGE("%s: pcm stream not ready", __func__);
3988 goto error_open;
3989 }
3990 ret = pcm_start(out->pcm);
3991 if (ret < 0) {
3992 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3993 goto error_open;
3994 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003995 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003996 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003997 unsigned int flags = PCM_OUT;
3998 unsigned int pcm_open_retry_count = 0;
3999 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4000 flags |= PCM_MMAP | PCM_NOIRQ;
4001 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004002 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004003 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004004 } else
4005 flags |= PCM_MONOTONIC;
4006
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004007 if ((adev->vr_audio_mode_enabled) &&
4008 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4009 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4010 "PCM_Dev %d Topology", out->pcm_device_id);
4011 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4012 if (!ctl) {
4013 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4014 __func__, mixer_ctl_name);
4015 } else {
4016 //if success use ULLPP
4017 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4018 __func__, mixer_ctl_name, out->pcm_device_id);
4019 //There is a still a possibility that some sessions
4020 // that request for FAST|RAW when 3D audio is active
4021 //can go through ULLPP. Ideally we expects apps to
4022 //listen to audio focus and stop concurrent playback
4023 //Also, we will look for mode flag (voice_in_communication)
4024 //before enabling the realtime flag.
4025 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4026 }
4027 }
4028
Surendar Karka91fa3682018-07-02 18:12:12 +05304029 if (out->realtime)
4030 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4031 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4032
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004033 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4034 flags, pcm_open_retry_count,
4035 &(out->config));
4036 if (out->pcm == NULL) {
4037 ret = -EIO;
4038 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004039 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004040
4041 if (is_haptic_usecase) {
4042 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4043 adev->haptic_pcm_device_id,
4044 flags, pcm_open_retry_count,
4045 &(adev->haptics_config));
4046 // failure to open haptics pcm shouldnt stop audio,
4047 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004048
4049 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4050 ALOGD("%s: enable haptic audio synchronization", __func__);
4051 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4052 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004053 }
4054
Surendar Karka91fa3682018-07-02 18:12:12 +05304055 if (!out->realtime)
4056 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304057 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004058
Zhou Song2b8f28f2017-09-11 10:51:38 +08004059 // apply volume for voip playback after path is set up
4060 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4061 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304062 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4063 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304064 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4065 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004066 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4067 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304068 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004069 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004070 /*
4071 * set custom channel map if:
4072 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4073 * 2. custom channel map has been set by client
4074 * else default channel map of FC/FR/FL can always be set to DSP
4075 */
4076 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4077 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4078 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004079 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4080 adev->dsp_bit_width_enforce_mode,
4081 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004083 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004084 out->compr = compress_open(adev->snd_card,
4085 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004086 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004087 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304088 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304089 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4090 adev->card_status = CARD_STATUS_OFFLINE;
4091 out->card_status = CARD_STATUS_OFFLINE;
4092 ret = -EIO;
4093 goto error_open;
4094 }
4095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004096 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004097 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004098 compress_close(out->compr);
4099 out->compr = NULL;
4100 ret = -EIO;
4101 goto error_open;
4102 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304103 /* compress_open sends params of the track, so reset the flag here */
4104 out->is_compr_metadata_avail = false;
4105
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004106 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004107 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004108
Fred Oh3f43e742015-03-04 18:42:34 -08004109 /* Since small bufs uses blocking writes, a write will be blocked
4110 for the default max poll time (20s) in the event of an SSR.
4111 Reduce the poll time to observe and deal with SSR faster.
4112 */
Ashish Jain5106d362016-05-11 19:23:33 +05304113 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004114 compress_set_max_poll_wait(out->compr, 1000);
4115 }
4116
Manish Dewangan69426c82017-01-30 17:35:36 +05304117 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304118 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304119
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004120 audio_extn_dts_create_state_notifier_node(out->usecase);
4121 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4122 popcount(out->channel_mask),
4123 out->playback_started);
4124
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004125#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304126 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004127 audio_extn_dolby_send_ddp_endp_params(adev);
4128#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304129 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4130 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004131 if (adev->visualizer_start_output != NULL)
4132 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4133 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304134 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004135 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004136 }
Derek Chenf13dd492018-11-13 14:53:51 -08004137
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004138 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004139 /* Update cached volume from media to offload/direct stream */
4140 struct listnode *node = NULL;
4141 list_for_each(node, &adev->active_outputs_list) {
4142 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4143 streams_output_ctxt_t,
4144 list);
4145 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4146 out->volume_l = out_ctxt->output->volume_l;
4147 out->volume_r = out_ctxt->output->volume_r;
4148 }
4149 }
4150 out_set_compr_volume(&out->stream,
4151 out->volume_l, out->volume_r);
4152 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004154
4155 if (ret == 0) {
4156 register_out_stream(out);
4157 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004158 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4159 ALOGE("%s: pcm stream not ready", __func__);
4160 goto error_open;
4161 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004162 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004163 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004164 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004165 if (ret < 0)
4166 goto error_open;
4167 }
4168 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004169 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304170 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004171 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004172
vivek mehtad15d2bf2019-05-17 13:35:10 -07004173 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4174 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4175 audio_low_latency_hint_start();
4176 }
4177
Manish Dewangan21a850a2017-08-14 12:03:55 +05304178 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004179 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004180 if (ret < 0)
4181 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4182 }
4183
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004184 // consider a scenario where on pause lower layers are tear down.
4185 // so on resume, swap mixer control need to be sent only when
4186 // backend is active, hence rather than sending from enable device
4187 // sending it from start of streamtream
4188
4189 platform_set_swap_channels(adev, true);
4190
Haynes Mathew George380745d2017-10-04 15:27:45 -07004191 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304192 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004193 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004194error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004195 if (adev->haptic_pcm) {
4196 pcm_close(adev->haptic_pcm);
4197 adev->haptic_pcm = NULL;
4198 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004199 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304200 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004202error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304203 /*
4204 * sleep 50ms to allow sufficient time for kernel
4205 * drivers to recover incases like SSR.
4206 */
4207 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004208error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004209 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304210 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004211 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212}
4213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214static int check_input_parameters(uint32_t sample_rate,
4215 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004216 int channel_count,
4217 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004219 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304221 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4222 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4223 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004224 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004225 !audio_extn_compr_cap_format_supported(format) &&
4226 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004227 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004228
Aalique Grahame22e49102018-12-18 14:23:57 -08004229 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4230 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4231 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4232 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4233 return -EINVAL;
4234 }
4235
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004236 switch (channel_count) {
4237 case 1:
4238 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304239 case 3:
4240 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004241 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004242 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304243 case 10:
4244 case 12:
4245 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004246 break;
4247 default:
4248 ret = -EINVAL;
4249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250
4251 switch (sample_rate) {
4252 case 8000:
4253 case 11025:
4254 case 12000:
4255 case 16000:
4256 case 22050:
4257 case 24000:
4258 case 32000:
4259 case 44100:
4260 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004261 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304262 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004263 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304264 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265 break;
4266 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004267 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268 }
4269
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004270 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271}
4272
Naresh Tanniru04f71882018-06-26 17:46:22 +05304273
4274/** Add a value in a list if not already present.
4275 * @return true if value was successfully inserted or already present,
4276 * false if the list is full and does not contain the value.
4277 */
4278static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4279 for (size_t i = 0; i < list_length; i++) {
4280 if (list[i] == value) return true; // value is already present
4281 if (list[i] == 0) { // no values in this slot
4282 list[i] = value;
4283 return true; // value inserted
4284 }
4285 }
4286 return false; // could not insert value
4287}
4288
4289/** Add channel_mask in supported_channel_masks if not already present.
4290 * @return true if channel_mask was successfully inserted or already present,
4291 * false if supported_channel_masks is full and does not contain channel_mask.
4292 */
4293static void register_channel_mask(audio_channel_mask_t channel_mask,
4294 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4295 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4296 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4297}
4298
4299/** Add format in supported_formats if not already present.
4300 * @return true if format was successfully inserted or already present,
4301 * false if supported_formats is full and does not contain format.
4302 */
4303static void register_format(audio_format_t format,
4304 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4305 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4306 "%s: stream can not declare supporting its format %x", __func__, format);
4307}
4308/** Add sample_rate in supported_sample_rates if not already present.
4309 * @return true if sample_rate was successfully inserted or already present,
4310 * false if supported_sample_rates is full and does not contain sample_rate.
4311 */
4312static void register_sample_rate(uint32_t sample_rate,
4313 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4314 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4315 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4316}
4317
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004318static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4319{
4320 uint32_t high = num1, low = num2, temp = 0;
4321
4322 if (!num1 || !num2)
4323 return 0;
4324
4325 if (num1 < num2) {
4326 high = num2;
4327 low = num1;
4328 }
4329
4330 while (low != 0) {
4331 temp = low;
4332 low = high % low;
4333 high = temp;
4334 }
4335 return (num1 * num2)/high;
4336}
4337
4338static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4339{
4340 uint32_t remainder = 0;
4341
4342 if (!multiplier)
4343 return num;
4344
4345 remainder = num % multiplier;
4346 if (remainder)
4347 num += (multiplier - remainder);
4348
4349 return num;
4350}
4351
Aalique Grahame22e49102018-12-18 14:23:57 -08004352static size_t get_stream_buffer_size(size_t duration_ms,
4353 uint32_t sample_rate,
4354 audio_format_t format,
4355 int channel_count,
4356 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357{
4358 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004359 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360
Aalique Grahame22e49102018-12-18 14:23:57 -08004361 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004362 if (is_low_latency)
4363 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304364
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004365 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004366 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367
Ralf Herzbd08d632018-09-28 15:50:49 +02004368 /* make sure the size is multiple of 32 bytes and additionally multiple of
4369 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004370 * At 48 kHz mono 16-bit PCM:
4371 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4372 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004373 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004374 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004375 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004376
4377 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378}
4379
Aalique Grahame22e49102018-12-18 14:23:57 -08004380static size_t get_input_buffer_size(uint32_t sample_rate,
4381 audio_format_t format,
4382 int channel_count,
4383 bool is_low_latency)
4384{
4385 /* Don't know if USB HIFI in this context so use true to be conservative */
4386 if (check_input_parameters(sample_rate, format, channel_count,
4387 true /*is_usb_hifi */) != 0)
4388 return 0;
4389
4390 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4391 sample_rate,
4392 format,
4393 channel_count,
4394 is_low_latency);
4395}
4396
Derek Chenf6318be2017-06-12 17:16:24 -04004397size_t get_output_period_size(uint32_t sample_rate,
4398 audio_format_t format,
4399 int channel_count,
4400 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304401{
4402 size_t size = 0;
4403 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4404
4405 if ((duration == 0) || (sample_rate == 0) ||
4406 (bytes_per_sample == 0) || (channel_count == 0)) {
4407 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4408 bytes_per_sample, channel_count);
4409 return -EINVAL;
4410 }
4411
4412 size = (sample_rate *
4413 duration *
4414 bytes_per_sample *
4415 channel_count) / 1000;
4416 /*
4417 * To have same PCM samples for all channels, the buffer size requires to
4418 * be multiple of (number of channels * bytes per sample)
4419 * For writes to succeed, the buffer must be written at address which is multiple of 32
4420 */
4421 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4422
4423 return (size/(channel_count * bytes_per_sample));
4424}
4425
Zhou Song48453a02018-01-10 17:50:59 +08004426static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304427{
4428 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004429 uint64_t written_frames = 0;
4430 uint64_t kernel_frames = 0;
4431 uint64_t dsp_frames = 0;
4432 uint64_t signed_frames = 0;
4433 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304434
4435 /* This adjustment accounts for buffering after app processor.
4436 * It is based on estimated DSP latency per use case, rather than exact.
4437 */
George Gao9ba8a142020-07-23 14:30:03 -07004438 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004439 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304440
Zhou Song48453a02018-01-10 17:50:59 +08004441 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004442 written_frames = out->written /
4443 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4444
Ashish Jain5106d362016-05-11 19:23:33 +05304445 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4446 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4447 * hence only estimate.
4448 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004449 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4450 kernel_frames = kernel_buffer_size /
4451 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304452
Weiyin Jiang4813da12020-05-28 00:37:28 +08004453 if (written_frames >= (kernel_frames + dsp_frames))
4454 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304455
Zhou Song48453a02018-01-10 17:50:59 +08004456 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304457 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004458 if (timestamp != NULL )
4459 *timestamp = out->writeAt;
4460 } else if (timestamp != NULL) {
4461 clock_gettime(CLOCK_MONOTONIC, timestamp);
4462 }
4463 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304464
Weiyin Jiang4813da12020-05-28 00:37:28 +08004465 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4466 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304467
4468 return actual_frames_rendered;
4469}
4470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4472{
4473 struct stream_out *out = (struct stream_out *)stream;
4474
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004475 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476}
4477
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004478static int out_set_sample_rate(struct audio_stream *stream __unused,
4479 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480{
4481 return -ENOSYS;
4482}
4483
4484static size_t out_get_buffer_size(const struct audio_stream *stream)
4485{
4486 struct stream_out *out = (struct stream_out *)stream;
4487
Varun Balaraje49253e2017-07-06 19:48:56 +05304488 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304489 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304490 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304491 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4492 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4493 else
4494 return out->compr_config.fragment_size;
4495 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004496 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304497 else if (is_offload_usecase(out->usecase) &&
4498 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304499 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004500
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004501 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004502 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503}
4504
4505static uint32_t out_get_channels(const struct audio_stream *stream)
4506{
4507 struct stream_out *out = (struct stream_out *)stream;
4508
4509 return out->channel_mask;
4510}
4511
4512static audio_format_t out_get_format(const struct audio_stream *stream)
4513{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004514 struct stream_out *out = (struct stream_out *)stream;
4515
4516 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517}
4518
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004519static int out_set_format(struct audio_stream *stream __unused,
4520 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521{
4522 return -ENOSYS;
4523}
4524
4525static int out_standby(struct audio_stream *stream)
4526{
4527 struct stream_out *out = (struct stream_out *)stream;
4528 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004529 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004530
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304531 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4532 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004534 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004536 if (adev->adm_deregister_stream)
4537 adev->adm_deregister_stream(adev->adm_data, out->handle);
4538
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004539 if (is_offload_usecase(out->usecase)) {
4540 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004541 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004542 pthread_mutex_unlock(&out->latch_lock);
4543 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004544
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004547 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4548 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304549 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004550 pthread_mutex_unlock(&adev->lock);
4551 pthread_mutex_unlock(&out->lock);
4552 ALOGD("VOIP output entered standby");
4553 return 0;
4554 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004555 if (out->pcm) {
4556 pcm_close(out->pcm);
4557 out->pcm = NULL;
4558 }
Meng Wanga09da002020-04-20 12:56:04 +08004559 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4560 if (adev->haptic_pcm) {
4561 pcm_close(adev->haptic_pcm);
4562 adev->haptic_pcm = NULL;
4563 }
4564
4565 if (adev->haptic_buffer != NULL) {
4566 free(adev->haptic_buffer);
4567 adev->haptic_buffer = NULL;
4568 adev->haptic_buffer_size = 0;
4569 }
4570 adev->haptic_pcm_device_id = 0;
4571 }
4572
Haynes Mathew George16081042017-05-31 17:16:49 -07004573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4574 do_stop = out->playback_started;
4575 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004576
4577 if (out->mmap_shared_memory_fd >= 0) {
4578 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4579 __func__, out->mmap_shared_memory_fd);
4580 close(out->mmap_shared_memory_fd);
4581 out->mmap_shared_memory_fd = -1;
4582 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004583 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004584 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004585 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304586 out->send_next_track_params = false;
4587 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004588 out->gapless_mdata.encoder_delay = 0;
4589 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004590 if (out->compr != NULL) {
4591 compress_close(out->compr);
4592 out->compr = NULL;
4593 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004594 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004595 if (do_stop) {
4596 stop_output_stream(out);
4597 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304598 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004599 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004600 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601 }
4602 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304603 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 return 0;
4605}
4606
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304607static int out_on_error(struct audio_stream *stream)
4608{
4609 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004610 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304611
4612 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004613 // always send CMD_ERROR for offload streams, this
4614 // is needed e.g. when SSR happens within compress_open
4615 // since the stream is active, offload_callback_thread is also active.
4616 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004617 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004618 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004619 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004620 }
4621 pthread_mutex_unlock(&out->lock);
4622
4623 status = out_standby(&out->stream.common);
4624
4625 lock_output_stream(out);
4626 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004627 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304628 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304629
4630 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4631 ALOGD("Setting previous card status if offline");
4632 out->prev_card_status_offline = true;
4633 }
4634
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304635 pthread_mutex_unlock(&out->lock);
4636
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004637 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304638}
4639
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304640/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004641 * standby implementation without locks, assumes that the callee already
4642 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304643 */
4644int out_standby_l(struct audio_stream *stream)
4645{
4646 struct stream_out *out = (struct stream_out *)stream;
4647 struct audio_device *adev = out->dev;
4648
4649 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4650 stream, out->usecase, use_case_table[out->usecase]);
4651
4652 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004653 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304654 if (adev->adm_deregister_stream)
4655 adev->adm_deregister_stream(adev->adm_data, out->handle);
4656
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004657 if (is_offload_usecase(out->usecase)) {
4658 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304659 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004660 pthread_mutex_unlock(&out->latch_lock);
4661 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304662
4663 out->standby = true;
4664 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4665 voice_extn_compress_voip_close_output_stream(stream);
4666 out->started = 0;
4667 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004668 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304669 return 0;
4670 } else if (!is_offload_usecase(out->usecase)) {
4671 if (out->pcm) {
4672 pcm_close(out->pcm);
4673 out->pcm = NULL;
4674 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004675 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4676 if (adev->haptic_pcm) {
4677 pcm_close(adev->haptic_pcm);
4678 adev->haptic_pcm = NULL;
4679 }
4680
4681 if (adev->haptic_buffer != NULL) {
4682 free(adev->haptic_buffer);
4683 adev->haptic_buffer = NULL;
4684 adev->haptic_buffer_size = 0;
4685 }
4686 adev->haptic_pcm_device_id = 0;
4687 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304688 } else {
4689 ALOGD("copl(%p):standby", out);
4690 out->send_next_track_params = false;
4691 out->is_compr_metadata_avail = false;
4692 out->gapless_mdata.encoder_delay = 0;
4693 out->gapless_mdata.encoder_padding = 0;
4694 if (out->compr != NULL) {
4695 compress_close(out->compr);
4696 out->compr = NULL;
4697 }
4698 }
4699 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004700 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304701 }
4702 ALOGD("%s: exit", __func__);
4703 return 0;
4704}
4705
Aalique Grahame22e49102018-12-18 14:23:57 -08004706static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707{
Aalique Grahame22e49102018-12-18 14:23:57 -08004708 struct stream_out *out = (struct stream_out *)stream;
4709
4710 // We try to get the lock for consistency,
4711 // but it isn't necessary for these variables.
4712 // If we're not in standby, we may be blocked on a write.
4713 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4714 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4715 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4716
Andy Hunga1f48fa2019-07-01 18:14:53 -07004717 char buffer[256]; // for statistics formatting
4718 if (!is_offload_usecase(out->usecase)) {
4719 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4720 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4721 }
4722
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004723 if (out->start_latency_ms.n > 0) {
4724 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4725 dprintf(fd, " Start latency ms: %s\n", buffer);
4726 }
4727
Aalique Grahame22e49102018-12-18 14:23:57 -08004728 if (locked) {
4729 pthread_mutex_unlock(&out->lock);
4730 }
4731
4732 // dump error info
4733 (void)error_log_dump(
4734 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004736 return 0;
4737}
4738
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004739static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4740{
4741 int ret = 0;
4742 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004743
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004744 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004745 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004746 return -EINVAL;
4747 }
4748
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304749 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004750
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004751 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4752 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304753 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004754 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004755 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4756 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304757 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004758 }
4759
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004760 ALOGV("%s new encoder delay %u and padding %u", __func__,
4761 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4762
4763 return 0;
4764}
4765
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004766static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4767{
4768 return out == adev->primary_output || out == adev->voice_tx_output;
4769}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004770
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304771// note: this call is safe only if the stream_cb is
4772// removed first in close_output_stream (as is done now).
4773static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4774{
4775 if (!stream || !parms)
4776 return;
4777
4778 struct stream_out *out = (struct stream_out *)stream;
4779 struct audio_device *adev = out->dev;
4780
4781 card_status_t status;
4782 int card;
4783 if (parse_snd_card_status(parms, &card, &status) < 0)
4784 return;
4785
4786 pthread_mutex_lock(&adev->lock);
4787 bool valid_cb = (card == adev->snd_card);
4788 pthread_mutex_unlock(&adev->lock);
4789
4790 if (!valid_cb)
4791 return;
4792
4793 lock_output_stream(out);
4794 if (out->card_status != status)
4795 out->card_status = status;
4796 pthread_mutex_unlock(&out->lock);
4797
4798 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4799 use_case_table[out->usecase],
4800 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4801
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304802 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304803 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304804 if (voice_is_call_state_active(adev) &&
4805 out == adev->primary_output) {
4806 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4807 pthread_mutex_lock(&adev->lock);
4808 voice_stop_call(adev);
4809 adev->mode = AUDIO_MODE_NORMAL;
4810 pthread_mutex_unlock(&adev->lock);
4811 }
4812 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304813 return;
4814}
4815
Kevin Rocardfce19002017-08-07 19:21:36 -07004816static int get_alive_usb_card(struct str_parms* parms) {
4817 int card;
4818 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4819 !audio_extn_usb_alive(card)) {
4820 return card;
4821 }
4822 return -ENODEV;
4823}
4824
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004825int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004826 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004827{
4828 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004829 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004830 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004831 bool bypass_a2dp = false;
4832 bool reconfig = false;
4833 unsigned long service_interval = 0;
4834
4835 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004836 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4837
4838 list_init(&new_devices);
4839 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004840
4841 lock_output_stream(out);
4842 pthread_mutex_lock(&adev->lock);
4843
4844 /*
4845 * When HDMI cable is unplugged the music playback is paused and
4846 * the policy manager sends routing=0. But the audioflinger continues
4847 * to write data until standby time (3sec). As the HDMI core is
4848 * turned off, the write gets blocked.
4849 * Avoid this by routing audio to speaker until standby.
4850 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004851 if (is_single_device_type_equal(&out->device_list,
4852 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004853 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854 !audio_extn_passthru_is_passthrough_stream(out) &&
4855 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004856 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857 }
4858 /*
4859 * When A2DP is disconnected the
4860 * music playback is paused and the policy manager sends routing=0
4861 * But the audioflinger continues to write data until standby time
4862 * (3sec). As BT is turned off, the write gets blocked.
4863 * Avoid this by routing audio to speaker until standby.
4864 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004865 if (is_a2dp_out_device_type(&out->device_list) &&
4866 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004867 !audio_extn_a2dp_source_is_ready() &&
4868 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004869 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870 }
4871 /*
4872 * When USB headset is disconnected the music platback paused
4873 * and the policy manager send routing=0. But if the USB is connected
4874 * back before the standby time, AFE is not closed and opened
4875 * when USB is connected back. So routing to speker will guarantee
4876 * AFE reconfiguration and AFE will be opend once USB is connected again
4877 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004878 if (is_usb_out_device_type(&out->device_list) &&
4879 list_empty(&new_devices) &&
4880 !audio_extn_usb_connected(NULL)) {
4881 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4882 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004883 /* To avoid a2dp to sco overlapping / BT device improper state
4884 * check with BT lib about a2dp streaming support before routing
4885 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004886 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004888 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4889 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004890 //combo usecase just by pass a2dp
4891 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4892 bypass_a2dp = true;
4893 } else {
4894 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4895 /* update device to a2dp and don't route as BT returned error
4896 * However it is still possible a2dp routing called because
4897 * of current active device disconnection (like wired headset)
4898 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004899 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004900 pthread_mutex_unlock(&adev->lock);
4901 pthread_mutex_unlock(&out->lock);
4902 goto error;
4903 }
4904 }
4905 }
4906
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004907 // Workaround: If routing to an non existing usb device, fail gracefully
4908 // The routing request will otherwise block during 10 second
4909 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004910 if (is_usb_out_device_type(&new_devices)) {
4911 struct str_parms *parms =
4912 str_parms_create_str(get_usb_device_address(&new_devices));
4913 if (!parms)
4914 goto error;
4915 if ((card = get_alive_usb_card(parms)) >= 0) {
4916 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4917 pthread_mutex_unlock(&adev->lock);
4918 pthread_mutex_unlock(&out->lock);
4919 str_parms_destroy(parms);
4920 ret = -ENOSYS;
4921 goto error;
4922 }
4923 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004924 }
4925
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004926 // Workaround: If routing to an non existing hdmi device, fail gracefully
4927 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4928 (platform_get_edid_info_v2(adev->platform,
4929 out->extconn.cs.controller,
4930 out->extconn.cs.stream) != 0)) {
4931 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4932 pthread_mutex_unlock(&adev->lock);
4933 pthread_mutex_unlock(&out->lock);
4934 ret = -ENOSYS;
4935 goto error;
4936 }
4937
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004938 /*
4939 * select_devices() call below switches all the usecases on the same
4940 * backend to the new device. Refer to check_usecases_codec_backend() in
4941 * the select_devices(). But how do we undo this?
4942 *
4943 * For example, music playback is active on headset (deep-buffer usecase)
4944 * and if we go to ringtones and select a ringtone, low-latency usecase
4945 * will be started on headset+speaker. As we can't enable headset+speaker
4946 * and headset devices at the same time, select_devices() switches the music
4947 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4948 * So when the ringtone playback is completed, how do we undo the same?
4949 *
4950 * We are relying on the out_set_parameters() call on deep-buffer output,
4951 * once the ringtone playback is ended.
4952 * NOTE: We should not check if the current devices are same as new devices.
4953 * Because select_devices() must be called to switch back the music
4954 * playback to headset.
4955 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004956 if (!list_empty(&new_devices)) {
4957 bool same_dev = compare_devices(&out->device_list, &new_devices);
4958 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004959
4960 if (output_drives_call(adev, out)) {
4961 if (!voice_is_call_state_active(adev)) {
4962 if (adev->mode == AUDIO_MODE_IN_CALL) {
4963 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004964 ret = voice_start_call(adev);
4965 }
4966 } else {
4967 adev->current_call_output = out;
4968 voice_update_devices_for_all_voice_usecases(adev);
4969 }
4970 }
4971
Mingshu Pang60536d72020-09-09 15:28:22 +08004972 if (is_usb_out_device_type(&out->device_list)) {
4973 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4974 audio_extn_usb_set_service_interval(true /*playback*/,
4975 service_interval,
4976 &reconfig);
4977 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4978 }
4979
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004980 if (!out->standby) {
4981 if (!same_dev) {
4982 ALOGV("update routing change");
4983 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4984 adev->perf_lock_opts,
4985 adev->perf_lock_opts_size);
4986 if (adev->adm_on_routing_change)
4987 adev->adm_on_routing_change(adev->adm_data,
4988 out->handle);
4989 }
4990 if (!bypass_a2dp) {
4991 select_devices(adev, out->usecase);
4992 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004993 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4994 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004995 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004996 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004997 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004998 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004999 }
5000
5001 if (!same_dev) {
5002 // on device switch force swap, lower functions will make sure
5003 // to check if swap is allowed or not.
5004 platform_set_swap_channels(adev, true);
5005 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5006 }
5007 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005008 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005009 pthread_mutex_lock(&out->latch_lock);
5010 if (out->a2dp_compress_mute) {
5011 out->a2dp_compress_mute = false;
5012 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5013 }
5014 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005015 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5016 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5017 }
5018 }
5019 }
5020
5021 pthread_mutex_unlock(&adev->lock);
5022 pthread_mutex_unlock(&out->lock);
5023
5024 /*handles device and call state changes*/
5025 audio_extn_extspk_update(adev->extspk);
5026
5027error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005028 ALOGV("%s: exit: code(%d)", __func__, ret);
5029 return ret;
5030}
5031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5033{
5034 struct stream_out *out = (struct stream_out *)stream;
5035 struct audio_device *adev = out->dev;
5036 struct str_parms *parms;
5037 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005038 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005039 int ext_controller = -1;
5040 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005041
sangwoobc677242013-08-08 16:53:43 +09005042 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005043 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305045 if (!parms)
5046 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005047
5048 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5049 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005050 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005051 out->extconn.cs.controller = ext_controller;
5052 out->extconn.cs.stream = ext_stream;
5053 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5054 use_case_table[out->usecase], out->extconn.cs.controller,
5055 out->extconn.cs.stream);
5056 }
5057
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005058 if (out == adev->primary_output) {
5059 pthread_mutex_lock(&adev->lock);
5060 audio_extn_set_parameters(adev, parms);
5061 pthread_mutex_unlock(&adev->lock);
5062 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005063 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005064 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005065 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005066
5067 audio_extn_dts_create_state_notifier_node(out->usecase);
5068 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5069 popcount(out->channel_mask),
5070 out->playback_started);
5071
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005072 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005073 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005074
Surendar Karkaf51b5842018-04-26 11:28:38 +05305075 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5076 sizeof(value));
5077 if (err >= 0) {
5078 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5079 audio_extn_send_dual_mono_mixing_coefficients(out);
5080 }
5081
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305082 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5083 if (err >= 0) {
5084 strlcpy(out->profile, value, sizeof(out->profile));
5085 ALOGV("updating stream profile with value '%s'", out->profile);
5086 lock_output_stream(out);
5087 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5088 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005089 &out->device_list, out->flags,
5090 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305091 out->sample_rate, out->bit_width,
5092 out->channel_mask, out->profile,
5093 &out->app_type_cfg);
5094 pthread_mutex_unlock(&out->lock);
5095 }
5096
Alexy Joseph98988832017-01-13 14:56:59 -08005097 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005098 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5099 // and vendor.audio.hal.output.suspend.supported is set to true
5100 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005101 //check suspend parameter only for low latency and if the property
5102 //is enabled
5103 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5104 ALOGI("%s: got suspend_playback %s", __func__, value);
5105 lock_output_stream(out);
5106 if (!strncmp(value, "false", 5)) {
5107 //suspend_playback=false is supposed to set QOS value back to 75%
5108 //the mixer control sent with value Enable will achieve that
5109 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5110 } else if (!strncmp (value, "true", 4)) {
5111 //suspend_playback=true is supposed to remove QOS value
5112 //resetting the mixer control will set the default value
5113 //for the mixer control which is Disable and this removes the QOS vote
5114 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5115 } else {
5116 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5117 " got %s", __func__, value);
5118 ret = -1;
5119 }
5120
5121 if (ret != 0) {
5122 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5123 __func__, out->pm_qos_mixer_path, ret);
5124 }
5125
5126 pthread_mutex_unlock(&out->lock);
5127 }
5128 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005129
Alexy Joseph98988832017-01-13 14:56:59 -08005130 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305132error:
Eric Laurent994a6932013-07-17 11:51:42 -07005133 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134 return ret;
5135}
5136
Paul McLeana50b7332018-12-17 08:24:21 -07005137static int in_set_microphone_direction(const struct audio_stream_in *stream,
5138 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005139 struct stream_in *in = (struct stream_in *)stream;
5140
5141 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5142
5143 in->direction = dir;
5144
5145 if (in->standby)
5146 return 0;
5147
5148 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005149}
5150
5151static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005152 struct stream_in *in = (struct stream_in *)stream;
5153
5154 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5155
5156 if (zoom > 1.0 || zoom < -1.0)
5157 return -EINVAL;
5158
5159 in->zoom = zoom;
5160
5161 if (in->standby)
5162 return 0;
5163
5164 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005165}
5166
5167
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005168static bool stream_get_parameter_channels(struct str_parms *query,
5169 struct str_parms *reply,
5170 audio_channel_mask_t *supported_channel_masks) {
5171 int ret = -1;
5172 char value[512];
5173 bool first = true;
5174 size_t i, j;
5175
5176 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5177 ret = 0;
5178 value[0] = '\0';
5179 i = 0;
5180 while (supported_channel_masks[i] != 0) {
5181 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5182 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5183 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305184 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005185
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305186 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005187 first = false;
5188 break;
5189 }
5190 }
5191 i++;
5192 }
5193 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5194 }
5195 return ret == 0;
5196}
5197
5198static bool stream_get_parameter_formats(struct str_parms *query,
5199 struct str_parms *reply,
5200 audio_format_t *supported_formats) {
5201 int ret = -1;
5202 char value[256];
5203 size_t i, j;
5204 bool first = true;
5205
5206 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5207 ret = 0;
5208 value[0] = '\0';
5209 i = 0;
5210 while (supported_formats[i] != 0) {
5211 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5212 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5213 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305214 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005215 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305216 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005217 first = false;
5218 break;
5219 }
5220 }
5221 i++;
5222 }
5223 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5224 }
5225 return ret == 0;
5226}
5227
5228static bool stream_get_parameter_rates(struct str_parms *query,
5229 struct str_parms *reply,
5230 uint32_t *supported_sample_rates) {
5231
5232 int i;
5233 char value[256];
5234 int ret = -1;
5235 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5236 ret = 0;
5237 value[0] = '\0';
5238 i=0;
5239 int cursor = 0;
5240 while (supported_sample_rates[i]) {
5241 int avail = sizeof(value) - cursor;
5242 ret = snprintf(value + cursor, avail, "%s%d",
5243 cursor > 0 ? "|" : "",
5244 supported_sample_rates[i]);
5245 if (ret < 0 || ret >= avail) {
5246 // if cursor is at the last element of the array
5247 // overwrite with \0 is duplicate work as
5248 // snprintf already put a \0 in place.
5249 // else
5250 // we had space to write the '|' at value[cursor]
5251 // (which will be overwritten) or no space to fill
5252 // the first element (=> cursor == 0)
5253 value[cursor] = '\0';
5254 break;
5255 }
5256 cursor += ret;
5257 ++i;
5258 }
5259 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5260 value);
5261 }
5262 return ret >= 0;
5263}
5264
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5266{
5267 struct stream_out *out = (struct stream_out *)stream;
5268 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005269 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270 char value[256];
5271 struct str_parms *reply = str_parms_create();
5272 size_t i, j;
5273 int ret;
5274 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005275
5276 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005277 if (reply) {
5278 str_parms_destroy(reply);
5279 }
5280 if (query) {
5281 str_parms_destroy(query);
5282 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005283 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5284 return NULL;
5285 }
5286
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005287 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5289 if (ret >= 0) {
5290 value[0] = '\0';
5291 i = 0;
5292 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005293 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5294 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005296 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005298 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299 first = false;
5300 break;
5301 }
5302 }
5303 i++;
5304 }
5305 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5306 str = str_parms_to_str(reply);
5307 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005308 voice_extn_out_get_parameters(out, query, reply);
5309 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005310 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005311
Alexy Joseph62142aa2015-11-16 15:10:34 -08005312
5313 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5314 if (ret >= 0) {
5315 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305316 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5317 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005318 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305319 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005320 } else {
5321 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305322 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005323 }
5324 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005325 if (str)
5326 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005327 str = str_parms_to_str(reply);
5328 }
5329
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005330 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5331 if (ret >= 0) {
5332 value[0] = '\0';
5333 i = 0;
5334 first = true;
5335 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005336 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5337 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005338 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005339 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005340 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005341 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005342 first = false;
5343 break;
5344 }
5345 }
5346 i++;
5347 }
5348 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005349 if (str)
5350 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005351 str = str_parms_to_str(reply);
5352 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005353
5354 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5355 if (ret >= 0) {
5356 value[0] = '\0';
5357 i = 0;
5358 first = true;
5359 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005360 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5361 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005362 if (!first) {
5363 strlcat(value, "|", sizeof(value));
5364 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005365 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005366 first = false;
5367 break;
5368 }
5369 }
5370 i++;
5371 }
5372 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5373 if (str)
5374 free(str);
5375 str = str_parms_to_str(reply);
5376 }
5377
Alexy Joseph98988832017-01-13 14:56:59 -08005378 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5379 //only low latency track supports suspend_resume
5380 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005381 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005382 if (str)
5383 free(str);
5384 str = str_parms_to_str(reply);
5385 }
5386
5387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005388 str_parms_destroy(query);
5389 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005390 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005391 return str;
5392}
5393
5394static uint32_t out_get_latency(const struct audio_stream_out *stream)
5395{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005396 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005397 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005398 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005399
Alexy Josephaa54c872014-12-03 02:46:47 -08005400 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305401 lock_output_stream(out);
5402 latency = audio_extn_utils_compress_get_dsp_latency(out);
5403 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005404 } else if ((out->realtime) ||
5405 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005406 // since the buffer won't be filled up faster than realtime,
5407 // return a smaller number
5408 if (out->config.rate)
5409 period_ms = (out->af_period_multiplier * out->config.period_size *
5410 1000) / (out->config.rate);
5411 else
5412 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005413 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005414 } else {
5415 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005416 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005417 }
5418
Zhou Songd2537a02020-06-11 22:04:46 +08005419 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005420 latency += audio_extn_a2dp_get_encoder_latency();
5421
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305422 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005423 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005424}
5425
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305426static float AmpToDb(float amplification)
5427{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305428 float db = DSD_VOLUME_MIN_DB;
5429 if (amplification > 0) {
5430 db = 20 * log10(amplification);
5431 if(db < DSD_VOLUME_MIN_DB)
5432 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305433 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305434 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305435}
5436
Arun Mirpuri5d170872019-03-26 13:21:31 -07005437static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5438 float right)
5439{
5440 struct stream_out *out = (struct stream_out *)stream;
5441 long volume = 0;
5442 char mixer_ctl_name[128] = "";
5443 struct audio_device *adev = out->dev;
5444 struct mixer_ctl *ctl = NULL;
5445 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5446 PCM_PLAYBACK);
5447
5448 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5449 "Playback %d Volume", pcm_device_id);
5450 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5451 if (!ctl) {
5452 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5453 __func__, mixer_ctl_name);
5454 return -EINVAL;
5455 }
5456 if (left != right)
5457 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5458 __func__, left, right);
5459 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5460 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5461 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5462 __func__, mixer_ctl_name, volume);
5463 return -EINVAL;
5464 }
5465 return 0;
5466}
5467
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305468static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5469 float right)
5470{
5471 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305472 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305473 char mixer_ctl_name[128];
5474 struct audio_device *adev = out->dev;
5475 struct mixer_ctl *ctl;
5476 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5477 PCM_PLAYBACK);
5478
5479 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5480 "Compress Playback %d Volume", pcm_device_id);
5481 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5482 if (!ctl) {
5483 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5484 __func__, mixer_ctl_name);
5485 return -EINVAL;
5486 }
5487 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5488 __func__, mixer_ctl_name, left, right);
5489 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5490 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5491 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5492
5493 return 0;
5494}
5495
Zhou Song2b8f28f2017-09-11 10:51:38 +08005496static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5497 float right)
5498{
5499 struct stream_out *out = (struct stream_out *)stream;
5500 char mixer_ctl_name[] = "App Type Gain";
5501 struct audio_device *adev = out->dev;
5502 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305503 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005504
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005505 if (!is_valid_volume(left, right)) {
5506 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5507 __func__, left, right);
5508 return -EINVAL;
5509 }
5510
Zhou Song2b8f28f2017-09-11 10:51:38 +08005511 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5512 if (!ctl) {
5513 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5514 __func__, mixer_ctl_name);
5515 return -EINVAL;
5516 }
5517
5518 set_values[0] = 0; //0: Rx Session 1:Tx Session
5519 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305520 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5521 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005522
5523 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5524 return 0;
5525}
5526
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305527static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5528 float right)
5529{
5530 struct stream_out *out = (struct stream_out *)stream;
5531 /* Volume control for pcm playback */
5532 if (left != right) {
5533 return -EINVAL;
5534 } else {
5535 char mixer_ctl_name[128];
5536 struct audio_device *adev = out->dev;
5537 struct mixer_ctl *ctl;
5538 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5539 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5540 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5541 if (!ctl) {
5542 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5543 return -EINVAL;
5544 }
5545
5546 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5547 int ret = mixer_ctl_set_value(ctl, 0, volume);
5548 if (ret < 0) {
5549 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5550 return -EINVAL;
5551 }
5552
5553 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5554
5555 return 0;
5556 }
5557}
5558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005559static int out_set_volume(struct audio_stream_out *stream, float left,
5560 float right)
5561{
Eric Laurenta9024de2013-04-04 09:19:12 -07005562 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005563 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305564 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005565
Arun Mirpuri5d170872019-03-26 13:21:31 -07005566 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005567 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5568 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005569 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005570 out->muted = (left == 0.0f);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005571 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005572 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005573 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305574 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005575 /*
5576 * Set mute or umute on HDMI passthrough stream.
5577 * Only take left channel into account.
5578 * Mute is 0 and unmute 1
5579 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305580 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305581 } else if (out->format == AUDIO_FORMAT_DSD){
5582 char mixer_ctl_name[128] = "DSD Volume";
5583 struct audio_device *adev = out->dev;
5584 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5585
5586 if (!ctl) {
5587 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5588 __func__, mixer_ctl_name);
5589 return -EINVAL;
5590 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305591 volume[0] = (long)(AmpToDb(left));
5592 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305593 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5594 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005595 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005596 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005597 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5598 struct listnode *node = NULL;
5599 list_for_each(node, &adev->active_outputs_list) {
5600 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5601 streams_output_ctxt_t,
5602 list);
5603 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5604 out->volume_l = out_ctxt->output->volume_l;
5605 out->volume_r = out_ctxt->output->volume_r;
5606 }
5607 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005608 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005609 if (!out->a2dp_compress_mute) {
5610 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5611 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005612 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005613 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005614 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005615 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005616 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305617 if (!out->a2dp_compress_mute)
5618 ret = out_set_compr_volume(stream, left, right);
5619 out->volume_l = left;
5620 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005621 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305622 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005623 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005624 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005625 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5626 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5627 if (!out->standby) {
5628 audio_extn_utils_send_app_type_gain(out->dev,
5629 out->app_type_cfg.app_type,
5630 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005631 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005632 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005633 out->volume_l = left;
5634 out->volume_r = right;
5635 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005636 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5637 ALOGV("%s: MMAP set volume called", __func__);
5638 if (!out->standby)
5639 ret = out_set_mmap_volume(stream, left, right);
5640 out->volume_l = left;
5641 out->volume_r = right;
5642 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305643 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305644 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5645 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305646 /* Volume control for pcm playback */
5647 if (!out->standby)
5648 ret = out_set_pcm_volume(stream, left, right);
5649 else
5650 out->apply_volume = true;
5651
5652 out->volume_l = left;
5653 out->volume_r = right;
5654 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005655 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5656 ALOGV("%s: bus device set volume called", __func__);
5657 if (!out->standby)
5658 ret = out_set_pcm_volume(stream, left, right);
5659 out->volume_l = left;
5660 out->volume_r = right;
5661 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005662 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005664 return -ENOSYS;
5665}
5666
Zhou Songc9672822017-08-16 16:01:39 +08005667static void update_frames_written(struct stream_out *out, size_t bytes)
5668{
5669 size_t bpf = 0;
5670
5671 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5672 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5673 bpf = 1;
5674 else if (!is_offload_usecase(out->usecase))
5675 bpf = audio_bytes_per_sample(out->format) *
5676 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005677
5678 pthread_mutex_lock(&out->position_query_lock);
5679 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005680 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005681 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5682 }
5683 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005684}
5685
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005686int split_and_write_audio_haptic_data(struct stream_out *out,
5687 const void *buffer, size_t bytes_to_write)
5688{
5689 struct audio_device *adev = out->dev;
5690
5691 int ret = 0;
5692 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5693 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5694 size_t frame_size = channel_count * bytes_per_sample;
5695 size_t frame_count = bytes_to_write / frame_size;
5696
5697 bool force_haptic_path =
5698 property_get_bool("vendor.audio.test_haptic", false);
5699
5700 // extract Haptics data from Audio buffer
5701 bool alloc_haptic_buffer = false;
5702 int haptic_channel_count = adev->haptics_config.channels;
5703 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5704 size_t audio_frame_size = frame_size - haptic_frame_size;
5705 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5706
5707 if (adev->haptic_buffer == NULL) {
5708 alloc_haptic_buffer = true;
5709 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5710 free(adev->haptic_buffer);
5711 adev->haptic_buffer_size = 0;
5712 alloc_haptic_buffer = true;
5713 }
5714
5715 if (alloc_haptic_buffer) {
5716 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005717 if(adev->haptic_buffer == NULL) {
5718 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5719 return -ENOMEM;
5720 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005721 adev->haptic_buffer_size = total_haptic_buffer_size;
5722 }
5723
5724 size_t src_index = 0, aud_index = 0, hap_index = 0;
5725 uint8_t *audio_buffer = (uint8_t *)buffer;
5726 uint8_t *haptic_buffer = adev->haptic_buffer;
5727
5728 // This is required for testing only. This works for stereo data only.
5729 // One channel is fed to audio stream and other to haptic stream for testing.
5730 if (force_haptic_path)
5731 audio_frame_size = haptic_frame_size = bytes_per_sample;
5732
5733 for (size_t i = 0; i < frame_count; i++) {
5734 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5735 audio_frame_size);
5736 aud_index += audio_frame_size;
5737 src_index += audio_frame_size;
5738
5739 if (adev->haptic_pcm)
5740 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5741 haptic_frame_size);
5742 hap_index += haptic_frame_size;
5743 src_index += haptic_frame_size;
5744
5745 // This is required for testing only.
5746 // Discard haptic channel data.
5747 if (force_haptic_path)
5748 src_index += haptic_frame_size;
5749 }
5750
5751 // write to audio pipeline
5752 ret = pcm_write(out->pcm, (void *)audio_buffer,
5753 frame_count * audio_frame_size);
5754
5755 // write to haptics pipeline
5756 if (adev->haptic_pcm)
5757 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5758 frame_count * haptic_frame_size);
5759
5760 return ret;
5761}
5762
Aalique Grahame22e49102018-12-18 14:23:57 -08005763#ifdef NO_AUDIO_OUT
5764static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5765 const void *buffer __unused, size_t bytes)
5766{
5767 struct stream_out *out = (struct stream_out *)stream;
5768
5769 /* No Output device supported other than BT for playback.
5770 * Sleep for the amount of buffer duration
5771 */
5772 lock_output_stream(out);
5773 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5774 (const struct audio_stream_out *)&out->stream) /
5775 out_get_sample_rate(&out->stream.common));
5776 pthread_mutex_unlock(&out->lock);
5777 return bytes;
5778}
5779#endif
5780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005781static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5782 size_t bytes)
5783{
5784 struct stream_out *out = (struct stream_out *)stream;
5785 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005786 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305787 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005788 const size_t frame_size = audio_stream_out_frame_size(stream);
5789 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305790 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005791 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005792
Haynes Mathew George380745d2017-10-04 15:27:45 -07005793 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005794 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305795
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305796 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005797
Dhananjay Kumarac341582017-02-23 23:42:25 +05305798 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305799 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305800 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5801 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005802 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305803 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305804 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305805 ALOGD(" %s: sound card is not active/SSR state", __func__);
5806 ret= -EIO;
5807 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305808 }
5809 }
5810
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305811 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305812 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305813 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305814 goto exit;
5815 }
5816
Haynes Mathew George16081042017-05-31 17:16:49 -07005817 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5818 ret = -EINVAL;
5819 goto exit;
5820 }
5821
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005822 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305823 !out->is_iec61937_info_available) {
5824
5825 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5826 out->is_iec61937_info_available = true;
5827 } else if (audio_extn_passthru_is_enabled()) {
5828 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305829 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305830
5831 if((out->format == AUDIO_FORMAT_DTS) ||
5832 (out->format == AUDIO_FORMAT_DTS_HD)) {
5833 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5834 buffer, bytes);
5835 if (ret) {
5836 if (ret != -ENOSYS) {
5837 out->is_iec61937_info_available = false;
5838 ALOGD("iec61937 transmission info not yet updated retry");
5839 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305840 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305841 /* if stream has started and after that there is
5842 * stream config change (iec transmission config)
5843 * then trigger select_device to update backend configuration.
5844 */
5845 out->stream_config_changed = true;
5846 pthread_mutex_lock(&adev->lock);
5847 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305848 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005849 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305850 ret = -EINVAL;
5851 goto exit;
5852 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305853 pthread_mutex_unlock(&adev->lock);
5854 out->stream_config_changed = false;
5855 out->is_iec61937_info_available = true;
5856 }
5857 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305858
Meng Wang4c32fb42020-01-16 17:57:11 +08005859#ifdef AUDIO_GKI_ENABLED
5860 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5861 compr_passthr = out->compr_config.codec->reserved[0];
5862#else
5863 compr_passthr = out->compr_config.codec->compr_passthr;
5864#endif
5865
Garmond Leung317cbf12017-09-13 16:20:50 -07005866 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005867 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305868 (out->is_iec61937_info_available == true)) {
5869 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5870 ret = -EINVAL;
5871 goto exit;
5872 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305873 }
5874 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305875
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005876 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005877 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005878 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5879 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305880 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305881 ret = -EIO;
5882 goto exit;
5883 }
5884 }
5885 }
5886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005888 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005889 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5890
Eric Laurent150dbfe2013-02-27 14:31:02 -08005891 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005892 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5893 ret = voice_extn_compress_voip_start_output_stream(out);
5894 else
5895 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005896 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005897 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005898 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005899 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900 goto exit;
5901 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305902 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005903 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005904
5905 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005906 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005907 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305908 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005909 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005910 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305911
5912 if ((out->is_iec61937_info_available == true) &&
5913 (audio_extn_passthru_is_passthrough_stream(out))&&
5914 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5915 ret = -EINVAL;
5916 goto exit;
5917 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305918 if (out->set_dual_mono)
5919 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005920
5921 // log startup time in ms.
5922 simple_stats_log(
5923 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005924 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005925
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005926 if (adev->is_channel_status_set == false &&
5927 compare_device_type(&out->device_list,
5928 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005929 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305930 adev->is_channel_status_set = true;
5931 }
5932
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305933 if ((adev->use_old_pspd_mix_ctrl == true) &&
5934 (out->pspd_coeff_sent == false)) {
5935 /*
5936 * Need to resend pspd coefficients after stream started for
5937 * older kernel version as it does not save the coefficients
5938 * and also stream has to be started for coeff to apply.
5939 */
5940 usecase = get_usecase_from_list(adev, out->usecase);
5941 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305942 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305943 out->pspd_coeff_sent = true;
5944 }
5945 }
5946
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005947 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005948 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005949 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005950 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005951 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5952 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305953 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5954 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005955 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305956 out->send_next_track_params = false;
5957 out->is_compr_metadata_avail = false;
5958 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005959 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305960 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305961 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005962
Ashish Jain83a6cc22016-06-28 14:34:17 +05305963 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305964 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305965 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305966 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005967 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305968 return -EINVAL;
5969 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305970 audio_format_t dst_format = out->hal_op_format;
5971 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305972
Dieter Luecking5d57def2018-09-07 14:23:37 +02005973 /* prevent division-by-zero */
5974 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5975 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5976 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5977 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305978 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005979 ATRACE_END();
5980 return -EINVAL;
5981 }
5982
Ashish Jainf1eaa582016-05-23 20:54:24 +05305983 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5984 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5985
Ashish Jain83a6cc22016-06-28 14:34:17 +05305986 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305987 dst_format,
5988 buffer,
5989 src_format,
5990 frames);
5991
Ashish Jain83a6cc22016-06-28 14:34:17 +05305992 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305993 bytes_to_write);
5994
5995 /*Convert written bytes in audio flinger format*/
5996 if (ret > 0)
5997 ret = ((ret * format_to_bitwidth_table[out->format]) /
5998 format_to_bitwidth_table[dst_format]);
5999 }
6000 } else
6001 ret = compress_write(out->compr, buffer, bytes);
6002
Zhou Songc9672822017-08-16 16:01:39 +08006003 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6004 update_frames_written(out, bytes);
6005
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306006 if (ret < 0)
6007 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006008 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306009 /*msg to cb thread only if non blocking write is enabled*/
6010 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306011 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006012 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306013 } else if (-ENETRESET == ret) {
6014 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306015 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306016 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306017 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006018 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306019 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006020 }
Ashish Jain5106d362016-05-11 19:23:33 +05306021
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306022 /* Call compr start only when non-zero bytes of data is there to be rendered */
6023 if (!out->playback_started && ret > 0) {
6024 int status = compress_start(out->compr);
6025 if (status < 0) {
6026 ret = status;
6027 ALOGE("%s: compr start failed with err %d", __func__, errno);
6028 goto exit;
6029 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006030 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006031 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006032 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006033 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006034 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006035
6036 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6037 popcount(out->channel_mask),
6038 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006039 }
6040 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006041 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 return ret;
6043 } else {
6044 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006045 size_t bytes_to_write = bytes;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006046 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006047 if (out->muted)
6048 memset((void *)buffer, 0, bytes);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006049 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006050 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6051 __func__, frames, frame_size, bytes_to_write);
6052
Aalique Grahame22e49102018-12-18 14:23:57 -08006053 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006054 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6055 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6056 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006057 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6058 int16_t *src = (int16_t *)buffer;
6059 int16_t *dst = (int16_t *)buffer;
6060
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006061 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006062 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006063 "out_write called for %s use case with wrong properties",
6064 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006065
6066 /*
6067 * FIXME: this can be removed once audio flinger mixer supports
6068 * mono output
6069 */
6070
6071 /*
6072 * Code below goes over each frame in the buffer and adds both
6073 * L and R samples and then divides by 2 to convert to mono
6074 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006075 if (channel_count == 2) {
6076 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6077 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6078 }
6079 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006080 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006081 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006082
6083 // Note: since out_get_presentation_position() is called alternating with out_write()
6084 // by AudioFlinger, we can check underruns using the prior timestamp read.
6085 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6086 if (out->last_fifo_valid) {
6087 // compute drain to see if there is an underrun.
6088 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306089 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6090 int64_t frames_by_time =
6091 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6092 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006093 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6094
6095 if (underrun > 0) {
6096 simple_stats_log(&out->fifo_underruns, underrun);
6097
6098 ALOGW("%s: underrun(%lld) "
6099 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6100 __func__,
6101 (long long)out->fifo_underruns.n,
6102 (long long)frames_by_time,
6103 (long long)out->last_fifo_frames_remaining);
6104 }
6105 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6106 }
6107
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306108 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006109
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006110 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006111
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006112 if (out->config.rate)
6113 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6114 out->config.rate;
6115
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006116 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006117 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6118
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006119 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006120 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006121 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306122 out->convert_buffer != NULL) {
6123
6124 memcpy_by_audio_format(out->convert_buffer,
6125 out->hal_op_format,
6126 buffer,
6127 out->hal_ip_format,
6128 out->config.period_size * out->config.channels);
6129
6130 ret = pcm_write(out->pcm, out->convert_buffer,
6131 (out->config.period_size *
6132 out->config.channels *
6133 format_to_bitwidth_table[out->hal_op_format]));
6134 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306135 /*
6136 * To avoid underrun in DSP when the application is not pumping
6137 * data at required rate, check for the no. of bytes and ignore
6138 * pcm_write if it is less than actual buffer size.
6139 * It is a work around to a change in compress VOIP driver.
6140 */
6141 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6142 bytes < (out->config.period_size * out->config.channels *
6143 audio_bytes_per_sample(out->format))) {
6144 size_t voip_buf_size =
6145 out->config.period_size * out->config.channels *
6146 audio_bytes_per_sample(out->format);
6147 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6148 __func__, bytes, voip_buf_size);
6149 usleep(((uint64_t)voip_buf_size - bytes) *
6150 1000000 / audio_stream_out_frame_size(stream) /
6151 out_get_sample_rate(&out->stream.common));
6152 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006153 } else {
6154 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6155 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6156 else
6157 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6158 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306159 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006160
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006161 release_out_focus(out);
6162
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306163 if (ret < 0)
6164 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006165 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306166 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006168 }
6169
6170exit:
Zhou Songc9672822017-08-16 16:01:39 +08006171 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306172 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306173 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006175 pthread_mutex_unlock(&out->lock);
6176
6177 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006178 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006179 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306180 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306181 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306182 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306183 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306184 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306185 out->standby = true;
6186 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306187 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006188 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6189 /* prevent division-by-zero */
6190 uint32_t stream_size = audio_stream_out_frame_size(stream);
6191 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006192
Dieter Luecking5d57def2018-09-07 14:23:37 +02006193 if ((stream_size == 0) || (srate == 0)) {
6194 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6195 ATRACE_END();
6196 return -EINVAL;
6197 }
6198 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6199 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006200 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306201 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006202 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006203 return ret;
6204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006205 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006206 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006207 return bytes;
6208}
6209
6210static int out_get_render_position(const struct audio_stream_out *stream,
6211 uint32_t *dsp_frames)
6212{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006213 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006214
6215 if (dsp_frames == NULL)
6216 return -EINVAL;
6217
6218 *dsp_frames = 0;
6219 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006220 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306221
6222 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6223 * this operation and adev_close_output_stream(where out gets reset).
6224 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306225 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006226 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306227 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006228 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306229 return 0;
6230 }
6231
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006232 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306233 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306234 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006235 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306236 if (ret < 0)
6237 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006238 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306239 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006240 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306241 if (-ENETRESET == ret) {
6242 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306243 out->card_status = CARD_STATUS_OFFLINE;
6244 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306245 } else if(ret < 0) {
6246 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306247 ret = -EINVAL;
6248 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306249 /*
6250 * Handle corner case where compress session is closed during SSR
6251 * and timestamp is queried
6252 */
6253 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306254 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306255 } else if (out->prev_card_status_offline) {
6256 ALOGE("ERROR: previously sound card was offline,return error");
6257 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306258 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306259 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006260 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306261 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306262 pthread_mutex_unlock(&out->lock);
6263 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006264 } else if (audio_is_linear_pcm(out->format)) {
6265 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006266 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006267 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006268 } else
6269 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006270}
6271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006272static int out_add_audio_effect(const struct audio_stream *stream __unused,
6273 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274{
6275 return 0;
6276}
6277
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006278static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6279 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006280{
6281 return 0;
6282}
6283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006284static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6285 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006286{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306287 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006288}
6289
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006290static int out_get_presentation_position(const struct audio_stream_out *stream,
6291 uint64_t *frames, struct timespec *timestamp)
6292{
6293 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306294 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006295 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006296
Ashish Jain5106d362016-05-11 19:23:33 +05306297 /* below piece of code is not guarded against any lock because audioFliner serializes
6298 * this operation and adev_close_output_stream( where out gets reset).
6299 */
6300 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306301 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006302 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306303 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6304 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6305 return 0;
6306 }
6307
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006308 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006309
Ashish Jain5106d362016-05-11 19:23:33 +05306310 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6311 ret = compress_get_tstamp(out->compr, &dsp_frames,
6312 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006313 // Adjustment accounts for A2dp encoder latency with offload usecases
6314 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006315 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006316 unsigned long offset =
6317 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6318 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6319 }
Ashish Jain5106d362016-05-11 19:23:33 +05306320 ALOGVV("%s rendered frames %ld sample_rate %d",
6321 __func__, dsp_frames, out->sample_rate);
6322 *frames = dsp_frames;
6323 if (ret < 0)
6324 ret = -errno;
6325 if (-ENETRESET == ret) {
6326 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306327 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306328 ret = -EINVAL;
6329 } else
6330 ret = 0;
6331 /* this is the best we can do */
6332 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006333 } else {
6334 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006335 unsigned int avail;
6336 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006337 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006338 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006339
Andy Hunga1f48fa2019-07-01 18:14:53 -07006340 if (out->kernel_buffer_size > avail) {
6341 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6342 } else {
6343 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6344 __func__, avail, out->kernel_buffer_size);
6345 avail = out->kernel_buffer_size;
6346 frames_temp = out->last_fifo_frames_remaining = 0;
6347 }
6348 out->last_fifo_valid = true;
6349 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6350
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006351 if (out->written >= frames_temp)
6352 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006353
Andy Hunga1f48fa2019-07-01 18:14:53 -07006354 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6355 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6356
Weiyin Jiangd4633762018-03-16 12:05:03 +08006357 // This adjustment accounts for buffering after app processor.
6358 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006359 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006360 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006361 if (signed_frames >= frames_temp)
6362 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006363
Weiyin Jiangd4633762018-03-16 12:05:03 +08006364 // Adjustment accounts for A2dp encoder latency with non offload usecases
6365 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006366 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006367 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6368 if (signed_frames >= frames_temp)
6369 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006370 }
6371
6372 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006373 *frames = signed_frames;
6374 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006375 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006376 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6377 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006378 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306379 *frames = out->written;
6380 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306381 if (is_offload_usecase(out->usecase))
6382 ret = -EINVAL;
6383 else
6384 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006385 }
6386 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006387 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006388 return ret;
6389}
6390
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006391static int out_set_callback(struct audio_stream_out *stream,
6392 stream_callback_t callback, void *cookie)
6393{
6394 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006395 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006396
6397 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006398 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006399 out->client_callback = callback;
6400 out->client_cookie = cookie;
6401 if (out->adsp_hdlr_stream_handle) {
6402 ret = audio_extn_adsp_hdlr_stream_set_callback(
6403 out->adsp_hdlr_stream_handle,
6404 callback,
6405 cookie);
6406 if (ret)
6407 ALOGW("%s:adsp hdlr callback registration failed %d",
6408 __func__, ret);
6409 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006410 pthread_mutex_unlock(&out->lock);
6411 return 0;
6412}
6413
6414static int out_pause(struct audio_stream_out* stream)
6415{
6416 struct stream_out *out = (struct stream_out *)stream;
6417 int status = -ENOSYS;
6418 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006419 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006420 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306421 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006422 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006423 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006424 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306425 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306426 status = compress_pause(out->compr);
6427
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006428 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006429
Mingming Yin21854652016-04-13 11:54:02 -07006430 if (audio_extn_passthru_is_active()) {
6431 ALOGV("offload use case, pause passthru");
6432 audio_extn_passthru_on_pause(out);
6433 }
6434
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306435 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006436 audio_extn_dts_notify_playback_state(out->usecase, 0,
6437 out->sample_rate, popcount(out->channel_mask),
6438 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006439 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006440 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006441 pthread_mutex_unlock(&out->lock);
6442 }
6443 return status;
6444}
6445
6446static int out_resume(struct audio_stream_out* stream)
6447{
6448 struct stream_out *out = (struct stream_out *)stream;
6449 int status = -ENOSYS;
6450 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006451 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006452 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306453 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006454 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006455 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006456 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306457 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306458 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006459 }
6460 if (!status) {
6461 out->offload_state = OFFLOAD_STATE_PLAYING;
6462 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306463 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006464 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6465 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006466 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006467 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006468 pthread_mutex_unlock(&out->lock);
6469 }
6470 return status;
6471}
6472
6473static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6474{
6475 struct stream_out *out = (struct stream_out *)stream;
6476 int status = -ENOSYS;
6477 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006478 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006479 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006480 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6481 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6482 else
6483 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6484 pthread_mutex_unlock(&out->lock);
6485 }
6486 return status;
6487}
6488
6489static int out_flush(struct audio_stream_out* stream)
6490{
6491 struct stream_out *out = (struct stream_out *)stream;
6492 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006493 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006494 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006495 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006496 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006497 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6498 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006499 } else {
6500 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6501 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006502 out->written = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006503 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006504 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006505 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006506 return 0;
6507 }
6508 return -ENOSYS;
6509}
6510
Haynes Mathew George16081042017-05-31 17:16:49 -07006511static int out_stop(const struct audio_stream_out* stream)
6512{
6513 struct stream_out *out = (struct stream_out *)stream;
6514 struct audio_device *adev = out->dev;
6515 int ret = -ENOSYS;
6516
6517 ALOGV("%s", __func__);
6518 pthread_mutex_lock(&adev->lock);
6519 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6520 out->playback_started && out->pcm != NULL) {
6521 pcm_stop(out->pcm);
6522 ret = stop_output_stream(out);
6523 out->playback_started = false;
6524 }
6525 pthread_mutex_unlock(&adev->lock);
6526 return ret;
6527}
6528
6529static int out_start(const struct audio_stream_out* stream)
6530{
6531 struct stream_out *out = (struct stream_out *)stream;
6532 struct audio_device *adev = out->dev;
6533 int ret = -ENOSYS;
6534
6535 ALOGV("%s", __func__);
6536 pthread_mutex_lock(&adev->lock);
6537 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6538 !out->playback_started && out->pcm != NULL) {
6539 ret = start_output_stream(out);
6540 if (ret == 0) {
6541 out->playback_started = true;
6542 }
6543 }
6544 pthread_mutex_unlock(&adev->lock);
6545 return ret;
6546}
6547
6548/*
6549 * Modify config->period_count based on min_size_frames
6550 */
6551static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6552{
6553 int periodCountRequested = (min_size_frames + config->period_size - 1)
6554 / config->period_size;
6555 int periodCount = MMAP_PERIOD_COUNT_MIN;
6556
6557 ALOGV("%s original config.period_size = %d config.period_count = %d",
6558 __func__, config->period_size, config->period_count);
6559
6560 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6561 periodCount *= 2;
6562 }
6563 config->period_count = periodCount;
6564
6565 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6566}
6567
Phil Burkfe17efd2019-03-25 10:23:35 -07006568// Read offset for the positional timestamp from a persistent vendor property.
6569// This is to workaround apparent inaccuracies in the timing information that
6570// is used by the AAudio timing model. The inaccuracies can cause glitches.
6571static int64_t get_mmap_out_time_offset() {
6572 const int32_t kDefaultOffsetMicros = 0;
6573 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006574 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006575 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6576 return mmap_time_offset_micros * (int64_t)1000;
6577}
6578
Haynes Mathew George16081042017-05-31 17:16:49 -07006579static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6580 int32_t min_size_frames,
6581 struct audio_mmap_buffer_info *info)
6582{
6583 struct stream_out *out = (struct stream_out *)stream;
6584 struct audio_device *adev = out->dev;
6585 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006586 unsigned int offset1 = 0;
6587 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006588 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006589 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006590 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006591
Arun Mirpuri5d170872019-03-26 13:21:31 -07006592 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306593 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006594 pthread_mutex_lock(&adev->lock);
6595
Sharad Sanglec6f32552018-05-04 16:15:38 +05306596 if (CARD_STATUS_OFFLINE == out->card_status ||
6597 CARD_STATUS_OFFLINE == adev->card_status) {
6598 ALOGW("out->card_status or adev->card_status offline, try again");
6599 ret = -EIO;
6600 goto exit;
6601 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306602 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006603 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6604 ret = -EINVAL;
6605 goto exit;
6606 }
6607 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6608 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6609 ret = -ENOSYS;
6610 goto exit;
6611 }
6612 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6613 if (out->pcm_device_id < 0) {
6614 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6615 __func__, out->pcm_device_id, out->usecase);
6616 ret = -EINVAL;
6617 goto exit;
6618 }
6619
6620 adjust_mmap_period_count(&out->config, min_size_frames);
6621
Arun Mirpuri5d170872019-03-26 13:21:31 -07006622 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006623 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6624 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6625 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306626 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306627 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6628 out->card_status = CARD_STATUS_OFFLINE;
6629 adev->card_status = CARD_STATUS_OFFLINE;
6630 ret = -EIO;
6631 goto exit;
6632 }
6633
Haynes Mathew George16081042017-05-31 17:16:49 -07006634 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6635 step = "open";
6636 ret = -ENODEV;
6637 goto exit;
6638 }
6639 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6640 if (ret < 0) {
6641 step = "begin";
6642 goto exit;
6643 }
juyuchen626833d2019-06-04 16:48:02 +08006644
6645 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006646 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006647 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006648 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006649 ret = platform_get_mmap_data_fd(adev->platform,
6650 out->pcm_device_id, 0 /*playback*/,
6651 &info->shared_memory_fd,
6652 &mmap_size);
6653 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006654 // Fall back to non exclusive mode
6655 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6656 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006657 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6658 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6659
Arun Mirpuri5d170872019-03-26 13:21:31 -07006660 if (mmap_size < buffer_size) {
6661 step = "mmap";
6662 goto exit;
6663 }
juyuchen626833d2019-06-04 16:48:02 +08006664 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006665 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006666 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006667 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006668
6669 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6670 if (ret < 0) {
6671 step = "commit";
6672 goto exit;
6673 }
6674
Phil Burkfe17efd2019-03-25 10:23:35 -07006675 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6676
Haynes Mathew George16081042017-05-31 17:16:49 -07006677 out->standby = false;
6678 ret = 0;
6679
Arun Mirpuri5d170872019-03-26 13:21:31 -07006680 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006681 __func__, info->shared_memory_address, info->buffer_size_frames);
6682
6683exit:
6684 if (ret != 0) {
6685 if (out->pcm == NULL) {
6686 ALOGE("%s: %s - %d", __func__, step, ret);
6687 } else {
6688 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6689 pcm_close(out->pcm);
6690 out->pcm = NULL;
6691 }
6692 }
6693 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306694 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006695 return ret;
6696}
6697
6698static int out_get_mmap_position(const struct audio_stream_out *stream,
6699 struct audio_mmap_position *position)
6700{
6701 struct stream_out *out = (struct stream_out *)stream;
6702 ALOGVV("%s", __func__);
6703 if (position == NULL) {
6704 return -EINVAL;
6705 }
6706 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006707 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006708 return -ENOSYS;
6709 }
6710 if (out->pcm == NULL) {
6711 return -ENOSYS;
6712 }
6713
6714 struct timespec ts = { 0, 0 };
6715 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6716 if (ret < 0) {
6717 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6718 return ret;
6719 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006720 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6721 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006722 return 0;
6723}
6724
6725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006726/** audio_stream_in implementation **/
6727static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6728{
6729 struct stream_in *in = (struct stream_in *)stream;
6730
6731 return in->config.rate;
6732}
6733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006734static int in_set_sample_rate(struct audio_stream *stream __unused,
6735 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006736{
6737 return -ENOSYS;
6738}
6739
6740static size_t in_get_buffer_size(const struct audio_stream *stream)
6741{
6742 struct stream_in *in = (struct stream_in *)stream;
6743
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006744 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6745 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006746 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6747 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306748 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306749 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006750
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006751 return in->config.period_size * in->af_period_multiplier *
6752 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006753}
6754
6755static uint32_t in_get_channels(const struct audio_stream *stream)
6756{
6757 struct stream_in *in = (struct stream_in *)stream;
6758
6759 return in->channel_mask;
6760}
6761
6762static audio_format_t in_get_format(const struct audio_stream *stream)
6763{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006764 struct stream_in *in = (struct stream_in *)stream;
6765
6766 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006767}
6768
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006769static int in_set_format(struct audio_stream *stream __unused,
6770 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006771{
6772 return -ENOSYS;
6773}
6774
6775static int in_standby(struct audio_stream *stream)
6776{
6777 struct stream_in *in = (struct stream_in *)stream;
6778 struct audio_device *adev = in->dev;
6779 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306780 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6781 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006782 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306783
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006784 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006785 if (!in->standby && in->is_st_session) {
6786 ALOGD("%s: sound trigger pcm stop lab", __func__);
6787 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006788 if (adev->num_va_sessions > 0)
6789 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006790 in->standby = 1;
6791 }
6792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006793 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006794 if (adev->adm_deregister_stream)
6795 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6796
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006797 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006799 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006800 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006801 voice_extn_compress_voip_close_input_stream(stream);
6802 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006803 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6804 do_stop = in->capture_started;
6805 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006806 if (in->mmap_shared_memory_fd >= 0) {
6807 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6808 __func__, in->mmap_shared_memory_fd);
6809 close(in->mmap_shared_memory_fd);
6810 in->mmap_shared_memory_fd = -1;
6811 }
Zhou Songa8895042016-07-05 17:54:22 +08006812 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306813 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306814 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006815 }
6816
Arun Mirpuri5d170872019-03-26 13:21:31 -07006817 if (in->pcm) {
6818 ATRACE_BEGIN("pcm_in_close");
6819 pcm_close(in->pcm);
6820 ATRACE_END();
6821 in->pcm = NULL;
6822 }
6823
Carter Hsu2e429db2019-05-14 18:50:52 +08006824 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006825 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006826
George Gao3018ede2019-10-23 13:23:00 -07006827 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6828 if (adev->num_va_sessions > 0)
6829 adev->num_va_sessions--;
6830 }
Quinn Malef6050362019-01-30 15:55:40 -08006831
Eric Laurent150dbfe2013-02-27 14:31:02 -08006832 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006833 }
6834 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006835 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 return status;
6837}
6838
Aalique Grahame22e49102018-12-18 14:23:57 -08006839static int in_dump(const struct audio_stream *stream,
6840 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006841{
Aalique Grahame22e49102018-12-18 14:23:57 -08006842 struct stream_in *in = (struct stream_in *)stream;
6843
6844 // We try to get the lock for consistency,
6845 // but it isn't necessary for these variables.
6846 // If we're not in standby, we may be blocked on a read.
6847 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6848 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6849 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6850 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6851
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006852 char buffer[256]; // for statistics formatting
6853 if (in->start_latency_ms.n > 0) {
6854 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6855 dprintf(fd, " Start latency ms: %s\n", buffer);
6856 }
6857
Aalique Grahame22e49102018-12-18 14:23:57 -08006858 if (locked) {
6859 pthread_mutex_unlock(&in->lock);
6860 }
6861
6862 // dump error info
6863 (void)error_log_dump(
6864 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006866 return 0;
6867}
6868
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306869static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6870{
6871 if (!stream || !parms)
6872 return;
6873
6874 struct stream_in *in = (struct stream_in *)stream;
6875 struct audio_device *adev = in->dev;
6876
6877 card_status_t status;
6878 int card;
6879 if (parse_snd_card_status(parms, &card, &status) < 0)
6880 return;
6881
6882 pthread_mutex_lock(&adev->lock);
6883 bool valid_cb = (card == adev->snd_card);
6884 pthread_mutex_unlock(&adev->lock);
6885
6886 if (!valid_cb)
6887 return;
6888
6889 lock_input_stream(in);
6890 if (in->card_status != status)
6891 in->card_status = status;
6892 pthread_mutex_unlock(&in->lock);
6893
6894 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6895 use_case_table[in->usecase],
6896 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6897
6898 // a better solution would be to report error back to AF and let
6899 // it put the stream to standby
6900 if (status == CARD_STATUS_OFFLINE)
6901 in_standby(&in->stream.common);
6902
6903 return;
6904}
6905
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006906int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006907 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006908 audio_source_t source)
6909{
6910 struct audio_device *adev = in->dev;
6911 int ret = 0;
6912
6913 lock_input_stream(in);
6914 pthread_mutex_lock(&adev->lock);
6915
6916 /* no audio source uses val == 0 */
6917 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6918 in->source = source;
6919 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6920 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6921 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6922 (in->config.rate == 8000 || in->config.rate == 16000 ||
6923 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6924 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6925 ret = voice_extn_compress_voip_open_input_stream(in);
6926 if (ret != 0) {
6927 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6928 __func__, ret);
6929 }
6930 }
6931 }
6932
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006933 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6934 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006935 // Workaround: If routing to an non existing usb device, fail gracefully
6936 // The routing request will otherwise block during 10 second
6937 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006938 struct str_parms *usb_addr =
6939 str_parms_create_str(get_usb_device_address(devices));
6940 if (is_usb_in_device_type(devices) && usb_addr &&
6941 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006942 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6943 ret = -ENOSYS;
6944 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006945 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006946 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006947 if (!in->standby && !in->is_st_session) {
6948 ALOGV("update input routing change");
6949 // inform adm before actual routing to prevent glitches.
6950 if (adev->adm_on_routing_change) {
6951 adev->adm_on_routing_change(adev->adm_data,
6952 in->capture_handle);
6953 ret = select_devices(adev, in->usecase);
6954 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6955 adev->adm_routing_changed = true;
6956 }
6957 }
6958 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006959 if (usb_addr)
6960 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006961 }
6962 pthread_mutex_unlock(&adev->lock);
6963 pthread_mutex_unlock(&in->lock);
6964
6965 ALOGD("%s: exit: status(%d)", __func__, ret);
6966 return ret;
6967}
6968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006969static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6970{
6971 struct stream_in *in = (struct stream_in *)stream;
6972 struct audio_device *adev = in->dev;
6973 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006974 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306975 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306977 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006978 parms = str_parms_create_str(kvpairs);
6979
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306980 if (!parms)
6981 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006982 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006983 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006984
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306985 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6986 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306987 strlcpy(in->profile, value, sizeof(in->profile));
6988 ALOGV("updating stream profile with value '%s'", in->profile);
6989 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6990 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006991 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306992 in->sample_rate, in->bit_width,
6993 in->profile, &in->app_type_cfg);
6994 }
6995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006996 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006997 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006998
6999 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307000error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307001 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007002}
7003
7004static char* in_get_parameters(const struct audio_stream *stream,
7005 const char *keys)
7006{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007007 struct stream_in *in = (struct stream_in *)stream;
7008 struct str_parms *query = str_parms_create_str(keys);
7009 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007010 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007011
7012 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007013 if (reply) {
7014 str_parms_destroy(reply);
7015 }
7016 if (query) {
7017 str_parms_destroy(query);
7018 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007019 ALOGE("in_get_parameters: failed to create query or reply");
7020 return NULL;
7021 }
7022
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007023 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007024
7025 voice_extn_in_get_parameters(in, query, reply);
7026
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007027 stream_get_parameter_channels(query, reply,
7028 &in->supported_channel_masks[0]);
7029 stream_get_parameter_formats(query, reply,
7030 &in->supported_formats[0]);
7031 stream_get_parameter_rates(query, reply,
7032 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007033 str = str_parms_to_str(reply);
7034 str_parms_destroy(query);
7035 str_parms_destroy(reply);
7036
7037 ALOGV("%s: exit: returns - %s", __func__, str);
7038 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007039}
7040
Aalique Grahame22e49102018-12-18 14:23:57 -08007041static int in_set_gain(struct audio_stream_in *stream,
7042 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007043{
Aalique Grahame22e49102018-12-18 14:23:57 -08007044 struct stream_in *in = (struct stream_in *)stream;
7045 char mixer_ctl_name[128];
7046 struct mixer_ctl *ctl;
7047 int ctl_value;
7048
7049 ALOGV("%s: gain %f", __func__, gain);
7050
7051 if (stream == NULL)
7052 return -EINVAL;
7053
7054 /* in_set_gain() only used to silence MMAP capture for now */
7055 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7056 return -ENOSYS;
7057
7058 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7059
7060 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7061 if (!ctl) {
7062 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7063 __func__, mixer_ctl_name);
7064 return -ENOSYS;
7065 }
7066
7067 if (gain < RECORD_GAIN_MIN)
7068 gain = RECORD_GAIN_MIN;
7069 else if (gain > RECORD_GAIN_MAX)
7070 gain = RECORD_GAIN_MAX;
7071 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7072
7073 mixer_ctl_set_value(ctl, 0, ctl_value);
7074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007075 return 0;
7076}
7077
7078static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7079 size_t bytes)
7080{
7081 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307082
7083 if (in == NULL) {
7084 ALOGE("%s: stream_in ptr is NULL", __func__);
7085 return -EINVAL;
7086 }
7087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007088 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307089 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307090 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007091
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007092 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307093
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007094 if (in->is_st_session) {
7095 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7096 /* Read from sound trigger HAL */
7097 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007098 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007099 if (adev->num_va_sessions < UINT_MAX)
7100 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007101 in->standby = 0;
7102 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007103 pthread_mutex_unlock(&in->lock);
7104 return bytes;
7105 }
7106
Haynes Mathew George16081042017-05-31 17:16:49 -07007107 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7108 ret = -ENOSYS;
7109 goto exit;
7110 }
7111
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007112 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7113 !in->standby && adev->adm_routing_changed) {
7114 ret = -ENOSYS;
7115 goto exit;
7116 }
7117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007118 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007119 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7120
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007121 pthread_mutex_lock(&adev->lock);
7122 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7123 ret = voice_extn_compress_voip_start_input_stream(in);
7124 else
7125 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007126 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7127 if (adev->num_va_sessions < UINT_MAX)
7128 adev->num_va_sessions++;
7129 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007130 pthread_mutex_unlock(&adev->lock);
7131 if (ret != 0) {
7132 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133 }
7134 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007135
7136 // log startup time in ms.
7137 simple_stats_log(
7138 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007140
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307141 /* Avoid read if capture_stopped is set */
7142 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7143 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7144 ret = -EINVAL;
7145 goto exit;
7146 }
7147
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007148 // what's the duration requested by the client?
7149 long ns = 0;
7150
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307151 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007152 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7153 in->config.rate;
7154
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007155 ret = request_in_focus(in, ns);
7156 if (ret != 0)
7157 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007158 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007159
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307160 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307161 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7162 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307163 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007164 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307165 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007166 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007167 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007168 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007169 } else if (audio_extn_ffv_get_stream() == in) {
7170 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307171 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007172 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307173 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7174 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7175 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7176 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307177 ret = -EINVAL;
7178 goto exit;
7179 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307180 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307181 ret = -errno;
7182 }
7183 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307184 /* bytes read is always set to bytes for non compress usecases */
7185 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007186 }
7187
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007188 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007190 /*
Quinn Malef6050362019-01-30 15:55:40 -08007191 * Instead of writing zeroes here, we could trust the hardware to always
7192 * provide zeroes when muted. This is also muted with voice recognition
7193 * usecases so that other clients do not have access to voice recognition
7194 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007195 */
Quinn Malef6050362019-01-30 15:55:40 -08007196 if ((ret == 0 && voice_get_mic_mute(adev) &&
7197 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007198 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7199 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007200 (adev->num_va_sessions &&
7201 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7202 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7203 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007204 memset(buffer, 0, bytes);
7205
7206exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307207 frame_size = audio_stream_in_frame_size(stream);
7208 if (frame_size > 0)
7209 in->frames_read += bytes_read/frame_size;
7210
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007211 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307212 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213 pthread_mutex_unlock(&in->lock);
7214
7215 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307216 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307217 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307218 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307219 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307220 in->standby = true;
7221 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307222 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307223 bytes_read = bytes;
7224 memset(buffer, 0, bytes);
7225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007226 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007227 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7228 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007229 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307230 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307231 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007232 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307233 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007234}
7235
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007236static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237{
7238 return 0;
7239}
7240
Aalique Grahame22e49102018-12-18 14:23:57 -08007241static int in_get_capture_position(const struct audio_stream_in *stream,
7242 int64_t *frames, int64_t *time)
7243{
7244 if (stream == NULL || frames == NULL || time == NULL) {
7245 return -EINVAL;
7246 }
7247 struct stream_in *in = (struct stream_in *)stream;
7248 int ret = -ENOSYS;
7249
7250 lock_input_stream(in);
7251 // note: ST sessions do not close the alsa pcm driver synchronously
7252 // on standby. Therefore, we may return an error even though the
7253 // pcm stream is still opened.
7254 if (in->standby) {
7255 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7256 "%s stream in standby but pcm not NULL for non ST session", __func__);
7257 goto exit;
7258 }
7259 if (in->pcm) {
7260 struct timespec timestamp;
7261 unsigned int avail;
7262 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7263 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007264 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007265 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007266 ret = 0;
7267 }
7268 }
7269exit:
7270 pthread_mutex_unlock(&in->lock);
7271 return ret;
7272}
7273
Carter Hsu2e429db2019-05-14 18:50:52 +08007274static int in_update_effect_list(bool add, effect_handle_t effect,
7275 struct listnode *head)
7276{
7277 struct listnode *node;
7278 struct in_effect_list *elist = NULL;
7279 struct in_effect_list *target = NULL;
7280 int ret = 0;
7281
7282 if (!head)
7283 return ret;
7284
7285 list_for_each(node, head) {
7286 elist = node_to_item(node, struct in_effect_list, list);
7287 if (elist->handle == effect) {
7288 target = elist;
7289 break;
7290 }
7291 }
7292
7293 if (add) {
7294 if (target) {
7295 ALOGD("effect %p already exist", effect);
7296 return ret;
7297 }
7298
7299 target = (struct in_effect_list *)
7300 calloc(1, sizeof(struct in_effect_list));
7301
7302 if (!target) {
7303 ALOGE("%s:fail to allocate memory", __func__);
7304 return -ENOMEM;
7305 }
7306
7307 target->handle = effect;
7308 list_add_tail(head, &target->list);
7309 } else {
7310 if (target) {
7311 list_remove(&target->list);
7312 free(target);
7313 }
7314 }
7315
7316 return ret;
7317}
7318
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007319static int add_remove_audio_effect(const struct audio_stream *stream,
7320 effect_handle_t effect,
7321 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007322{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007323 struct stream_in *in = (struct stream_in *)stream;
7324 int status = 0;
7325 effect_descriptor_t desc;
7326
7327 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007328 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7329
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007330 if (status != 0)
7331 return status;
7332
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007333 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007334 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007335 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007336 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7337 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007338 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007339
7340 in_update_effect_list(enable, effect, &in->aec_list);
7341 enable = !list_empty(&in->aec_list);
7342 if (enable == in->enable_aec)
7343 goto exit;
7344
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007345 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007346 ALOGD("AEC enable %d", enable);
7347
Aalique Grahame22e49102018-12-18 14:23:57 -08007348 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7349 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7350 in->dev->enable_voicerx = enable;
7351 struct audio_usecase *usecase;
7352 struct listnode *node;
7353 list_for_each(node, &in->dev->usecase_list) {
7354 usecase = node_to_item(node, struct audio_usecase, list);
7355 if (usecase->type == PCM_PLAYBACK)
7356 select_devices(in->dev, usecase->id);
7357 }
7358 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007359 if (!in->standby) {
7360 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7361 select_devices(in->dev, in->usecase);
7362 }
7363
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007364 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007365 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7366
7367 in_update_effect_list(enable, effect, &in->ns_list);
7368 enable = !list_empty(&in->ns_list);
7369 if (enable == in->enable_ns)
7370 goto exit;
7371
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007372 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007373 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007374 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007375 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7376 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007377 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7378 select_devices(in->dev, in->usecase);
7379 } else
7380 select_devices(in->dev, in->usecase);
7381 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007382 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007383exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007384 pthread_mutex_unlock(&in->dev->lock);
7385 pthread_mutex_unlock(&in->lock);
7386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007387 return 0;
7388}
7389
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007390static int in_add_audio_effect(const struct audio_stream *stream,
7391 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007392{
Eric Laurent994a6932013-07-17 11:51:42 -07007393 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007394 return add_remove_audio_effect(stream, effect, true);
7395}
7396
7397static int in_remove_audio_effect(const struct audio_stream *stream,
7398 effect_handle_t effect)
7399{
Eric Laurent994a6932013-07-17 11:51:42 -07007400 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007401 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007402}
7403
Derek Chenf939fb72018-11-13 13:34:41 -08007404streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7405 audio_io_handle_t input)
7406{
7407 struct listnode *node;
7408
7409 list_for_each(node, &dev->active_inputs_list) {
7410 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7411 streams_input_ctxt_t,
7412 list);
7413 if (in_ctxt->input->capture_handle == input) {
7414 return in_ctxt;
7415 }
7416 }
7417 return NULL;
7418}
7419
7420streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7421 audio_io_handle_t output)
7422{
7423 struct listnode *node;
7424
7425 list_for_each(node, &dev->active_outputs_list) {
7426 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7427 streams_output_ctxt_t,
7428 list);
7429 if (out_ctxt->output->handle == output) {
7430 return out_ctxt;
7431 }
7432 }
7433 return NULL;
7434}
7435
Haynes Mathew George16081042017-05-31 17:16:49 -07007436static int in_stop(const struct audio_stream_in* stream)
7437{
7438 struct stream_in *in = (struct stream_in *)stream;
7439 struct audio_device *adev = in->dev;
7440
7441 int ret = -ENOSYS;
7442 ALOGV("%s", __func__);
7443 pthread_mutex_lock(&adev->lock);
7444 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7445 in->capture_started && in->pcm != NULL) {
7446 pcm_stop(in->pcm);
7447 ret = stop_input_stream(in);
7448 in->capture_started = false;
7449 }
7450 pthread_mutex_unlock(&adev->lock);
7451 return ret;
7452}
7453
7454static int in_start(const struct audio_stream_in* stream)
7455{
7456 struct stream_in *in = (struct stream_in *)stream;
7457 struct audio_device *adev = in->dev;
7458 int ret = -ENOSYS;
7459
7460 ALOGV("%s in %p", __func__, in);
7461 pthread_mutex_lock(&adev->lock);
7462 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7463 !in->capture_started && in->pcm != NULL) {
7464 if (!in->capture_started) {
7465 ret = start_input_stream(in);
7466 if (ret == 0) {
7467 in->capture_started = true;
7468 }
7469 }
7470 }
7471 pthread_mutex_unlock(&adev->lock);
7472 return ret;
7473}
7474
Phil Burke0a86d12019-02-16 22:28:11 -08007475// Read offset for the positional timestamp from a persistent vendor property.
7476// This is to workaround apparent inaccuracies in the timing information that
7477// is used by the AAudio timing model. The inaccuracies can cause glitches.
7478static int64_t in_get_mmap_time_offset() {
7479 const int32_t kDefaultOffsetMicros = 0;
7480 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007481 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007482 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7483 return mmap_time_offset_micros * (int64_t)1000;
7484}
7485
Haynes Mathew George16081042017-05-31 17:16:49 -07007486static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7487 int32_t min_size_frames,
7488 struct audio_mmap_buffer_info *info)
7489{
7490 struct stream_in *in = (struct stream_in *)stream;
7491 struct audio_device *adev = in->dev;
7492 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007493 unsigned int offset1 = 0;
7494 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007495 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007496 uint32_t mmap_size = 0;
7497 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007498
7499 pthread_mutex_lock(&adev->lock);
7500 ALOGV("%s in %p", __func__, in);
7501
Sharad Sanglec6f32552018-05-04 16:15:38 +05307502 if (CARD_STATUS_OFFLINE == in->card_status||
7503 CARD_STATUS_OFFLINE == adev->card_status) {
7504 ALOGW("in->card_status or adev->card_status offline, try again");
7505 ret = -EIO;
7506 goto exit;
7507 }
7508
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307509 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007510 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7511 ret = -EINVAL;
7512 goto exit;
7513 }
7514 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7515 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7516 ALOGV("%s in %p", __func__, in);
7517 ret = -ENOSYS;
7518 goto exit;
7519 }
7520 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7521 if (in->pcm_device_id < 0) {
7522 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7523 __func__, in->pcm_device_id, in->usecase);
7524 ret = -EINVAL;
7525 goto exit;
7526 }
7527
7528 adjust_mmap_period_count(&in->config, min_size_frames);
7529
7530 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7531 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7532 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7533 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307534 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307535 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7536 in->card_status = CARD_STATUS_OFFLINE;
7537 adev->card_status = CARD_STATUS_OFFLINE;
7538 ret = -EIO;
7539 goto exit;
7540 }
7541
Haynes Mathew George16081042017-05-31 17:16:49 -07007542 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7543 step = "open";
7544 ret = -ENODEV;
7545 goto exit;
7546 }
7547
7548 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7549 if (ret < 0) {
7550 step = "begin";
7551 goto exit;
7552 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007553
juyuchen626833d2019-06-04 16:48:02 +08007554 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007555 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7556 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7557 info->burst_size_frames = in->config.period_size;
7558 ret = platform_get_mmap_data_fd(adev->platform,
7559 in->pcm_device_id, 1 /*capture*/,
7560 &info->shared_memory_fd,
7561 &mmap_size);
7562 if (ret < 0) {
7563 // Fall back to non exclusive mode
7564 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7565 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007566 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7567 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7568
Arun Mirpuri5d170872019-03-26 13:21:31 -07007569 if (mmap_size < buffer_size) {
7570 step = "mmap";
7571 goto exit;
7572 }
juyuchen626833d2019-06-04 16:48:02 +08007573 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007574 }
7575
7576 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007577
7578 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7579 if (ret < 0) {
7580 step = "commit";
7581 goto exit;
7582 }
7583
Phil Burke0a86d12019-02-16 22:28:11 -08007584 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7585
Haynes Mathew George16081042017-05-31 17:16:49 -07007586 in->standby = false;
7587 ret = 0;
7588
7589 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7590 __func__, info->shared_memory_address, info->buffer_size_frames);
7591
7592exit:
7593 if (ret != 0) {
7594 if (in->pcm == NULL) {
7595 ALOGE("%s: %s - %d", __func__, step, ret);
7596 } else {
7597 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7598 pcm_close(in->pcm);
7599 in->pcm = NULL;
7600 }
7601 }
7602 pthread_mutex_unlock(&adev->lock);
7603 return ret;
7604}
7605
7606static int in_get_mmap_position(const struct audio_stream_in *stream,
7607 struct audio_mmap_position *position)
7608{
7609 struct stream_in *in = (struct stream_in *)stream;
7610 ALOGVV("%s", __func__);
7611 if (position == NULL) {
7612 return -EINVAL;
7613 }
7614 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7615 return -ENOSYS;
7616 }
7617 if (in->pcm == NULL) {
7618 return -ENOSYS;
7619 }
7620 struct timespec ts = { 0, 0 };
7621 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7622 if (ret < 0) {
7623 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7624 return ret;
7625 }
Phil Burke0a86d12019-02-16 22:28:11 -08007626 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7627 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007628 return 0;
7629}
7630
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307631static int in_get_active_microphones(const struct audio_stream_in *stream,
7632 struct audio_microphone_characteristic_t *mic_array,
7633 size_t *mic_count) {
7634 struct stream_in *in = (struct stream_in *)stream;
7635 struct audio_device *adev = in->dev;
7636 ALOGVV("%s", __func__);
7637
7638 lock_input_stream(in);
7639 pthread_mutex_lock(&adev->lock);
7640 int ret = platform_get_active_microphones(adev->platform,
7641 audio_channel_count_from_in_mask(in->channel_mask),
7642 in->usecase, mic_array, mic_count);
7643 pthread_mutex_unlock(&adev->lock);
7644 pthread_mutex_unlock(&in->lock);
7645
7646 return ret;
7647}
7648
7649static int adev_get_microphones(const struct audio_hw_device *dev,
7650 struct audio_microphone_characteristic_t *mic_array,
7651 size_t *mic_count) {
7652 struct audio_device *adev = (struct audio_device *)dev;
7653 ALOGVV("%s", __func__);
7654
7655 pthread_mutex_lock(&adev->lock);
7656 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7657 pthread_mutex_unlock(&adev->lock);
7658
7659 return ret;
7660}
juyuchendb308c22019-01-21 11:57:17 -07007661
7662static void in_update_sink_metadata(struct audio_stream_in *stream,
7663 const struct sink_metadata *sink_metadata) {
7664
7665 if (stream == NULL
7666 || sink_metadata == NULL
7667 || sink_metadata->tracks == NULL) {
7668 return;
7669 }
7670
7671 int error = 0;
7672 struct stream_in *in = (struct stream_in *)stream;
7673 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007674 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007675 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007676
7677 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007678
7679 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007680 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007681
7682 lock_input_stream(in);
7683 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007684 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007685
Zhou Song62ea0282020-03-22 19:53:01 +08007686 is_ha_usecase = adev->ha_proxy_enable ?
7687 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7688 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7689 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007690 && adev->voice_tx_output != NULL) {
7691 /* Use the rx device from afe-proxy record to route voice call because
7692 there is no routing if tx device is on primary hal and rx device
7693 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007694 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007695
7696 if (!voice_is_call_state_active(adev)) {
7697 if (adev->mode == AUDIO_MODE_IN_CALL) {
7698 adev->current_call_output = adev->voice_tx_output;
7699 error = voice_start_call(adev);
7700 if (error != 0)
7701 ALOGE("%s: start voice call failed %d", __func__, error);
7702 }
7703 } else {
7704 adev->current_call_output = adev->voice_tx_output;
7705 voice_update_devices_for_all_voice_usecases(adev);
7706 }
7707 }
7708
7709 pthread_mutex_unlock(&adev->lock);
7710 pthread_mutex_unlock(&in->lock);
7711}
7712
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307713int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007714 audio_io_handle_t handle,
7715 audio_devices_t devices,
7716 audio_output_flags_t flags,
7717 struct audio_config *config,
7718 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007719 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007720{
7721 struct audio_device *adev = (struct audio_device *)dev;
7722 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307723 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007724 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007725 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307726 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007727 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7728 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7729 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7730 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007731 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007732 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7733 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007734 bool force_haptic_path =
7735 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007736 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007737#ifdef AUDIO_GKI_ENABLED
7738 __s32 *generic_dec;
7739#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007740
kunleizdff872d2018-08-20 14:40:33 +08007741 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007742 is_usb_dev = false;
7743 devices = AUDIO_DEVICE_OUT_SPEAKER;
7744 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7745 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007746 if (config->format == AUDIO_FORMAT_DEFAULT)
7747 config->format = AUDIO_FORMAT_PCM_16_BIT;
7748 if (config->sample_rate == 0)
7749 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7750 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7751 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007752 }
7753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007754 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307755
Rahul Sharma99770982019-03-06 17:05:26 +05307756 pthread_mutex_lock(&adev->lock);
7757 if (out_get_stream(adev, handle) != NULL) {
7758 ALOGW("%s, output stream already opened", __func__);
7759 ret = -EEXIST;
7760 }
7761 pthread_mutex_unlock(&adev->lock);
7762 if (ret)
7763 return ret;
7764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007765 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7766
Mingming Yin3a941d42016-02-17 18:08:05 -08007767 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007768 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7769 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307770
7771
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007772 if (!out) {
7773 return -ENOMEM;
7774 }
7775
Haynes Mathew George204045b2015-02-25 20:32:03 -08007776 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007777 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007778 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007779 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007780 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007782 if (devices == AUDIO_DEVICE_NONE)
7783 devices = AUDIO_DEVICE_OUT_SPEAKER;
7784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007785 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007786 list_init(&out->device_list);
7787 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007788 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007789 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007790 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307791 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307792 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7793 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7794 else
7795 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007796 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007797 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007798 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307799 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307800 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307801 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007802 out->hal_output_suspend_supported = 0;
7803 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307804 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307805 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307806 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007807 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007808
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307809 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307810 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007811 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7812
Aalique Grahame22e49102018-12-18 14:23:57 -08007813 if (direct_dev &&
7814 (audio_is_linear_pcm(out->format) ||
7815 config->format == AUDIO_FORMAT_DEFAULT) &&
7816 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7817 audio_format_t req_format = config->format;
7818 audio_channel_mask_t req_channel_mask = config->channel_mask;
7819 uint32_t req_sample_rate = config->sample_rate;
7820
7821 pthread_mutex_lock(&adev->lock);
7822 if (is_hdmi) {
7823 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7824 ret = read_hdmi_sink_caps(out);
7825 if (config->sample_rate == 0)
7826 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7827 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7828 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7829 if (config->format == AUDIO_FORMAT_DEFAULT)
7830 config->format = AUDIO_FORMAT_PCM_16_BIT;
7831 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007832 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7833 &config->format,
7834 &out->supported_formats[0],
7835 MAX_SUPPORTED_FORMATS,
7836 &config->channel_mask,
7837 &out->supported_channel_masks[0],
7838 MAX_SUPPORTED_CHANNEL_MASKS,
7839 &config->sample_rate,
7840 &out->supported_sample_rates[0],
7841 MAX_SUPPORTED_SAMPLE_RATES);
7842 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007843 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007844
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007845 pthread_mutex_unlock(&adev->lock);
7846 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007847 if (ret == -ENOSYS) {
7848 /* ignore and go with default */
7849 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007850 }
7851 // For MMAP NO IRQ, allow conversions in ADSP
7852 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7853 goto error_open;
7854 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007855 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007856 goto error_open;
7857 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007858
7859 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7860 config->sample_rate = req_sample_rate;
7861 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7862 config->channel_mask = req_channel_mask;
7863 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7864 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007865 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007866
7867 out->sample_rate = config->sample_rate;
7868 out->channel_mask = config->channel_mask;
7869 out->format = config->format;
7870 if (is_hdmi) {
7871 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7872 out->config = pcm_config_hdmi_multi;
7873 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7874 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7875 out->config = pcm_config_mmap_playback;
7876 out->stream.start = out_start;
7877 out->stream.stop = out_stop;
7878 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7879 out->stream.get_mmap_position = out_get_mmap_position;
7880 } else {
7881 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7882 out->config = pcm_config_hifi;
7883 }
7884
7885 out->config.rate = out->sample_rate;
7886 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7887 if (is_hdmi) {
7888 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7889 audio_bytes_per_sample(out->format));
7890 }
7891 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007892 }
7893
Derek Chenf6318be2017-06-12 17:16:24 -04007894 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007895 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007896 /* extract car audio stream index */
7897 out->car_audio_stream =
7898 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7899 if (out->car_audio_stream < 0) {
7900 ALOGE("%s: invalid car audio stream %x",
7901 __func__, out->car_audio_stream);
7902 ret = -EINVAL;
7903 goto error_open;
7904 }
Derek Chen5f67a942020-02-24 23:08:13 -08007905 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007906 }
7907
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007908 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007909 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007910 if (!voice_extn_is_compress_voip_supported()) {
7911 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7912 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007913 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307914 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007915 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7916 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007917 out->volume_l = INVALID_OUT_VOLUME;
7918 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007919
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007920 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007921 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007922 uint32_t channel_count =
7923 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307924 out->config.channels = channel_count;
7925
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007926 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7927 out->sample_rate, out->format,
7928 channel_count, false);
7929 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7930 if (frame_size != 0)
7931 out->config.period_size = buffer_size / frame_size;
7932 else
7933 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007934 }
7935 } else {
7936 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7937 voice_extn_compress_voip_is_active(out->dev)) &&
7938 (voice_extn_compress_voip_is_config_supported(config))) {
7939 ret = voice_extn_compress_voip_open_output_stream(out);
7940 if (ret != 0) {
7941 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7942 __func__, ret);
7943 goto error_open;
7944 }
Sujin Panicker19027262019-09-16 18:28:06 +05307945 } else {
7946 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7947 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007948 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007949 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007950 } else if (audio_is_linear_pcm(out->format) &&
7951 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7952 out->channel_mask = config->channel_mask;
7953 out->sample_rate = config->sample_rate;
7954 out->format = config->format;
7955 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7956 // does this change?
7957 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7958 out->config.rate = config->sample_rate;
7959 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7960 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7961 audio_bytes_per_sample(config->format));
7962 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007963 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307964 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307965 pthread_mutex_lock(&adev->lock);
7966 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7967 pthread_mutex_unlock(&adev->lock);
7968
7969 // reject offload during card offline to allow
7970 // fallback to s/w paths
7971 if (offline) {
7972 ret = -ENODEV;
7973 goto error_open;
7974 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007975
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007976 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7977 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7978 ALOGE("%s: Unsupported Offload information", __func__);
7979 ret = -EINVAL;
7980 goto error_open;
7981 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007982
Atul Khare3fa6e542017-08-09 00:56:17 +05307983 if (config->offload_info.format == 0)
7984 config->offload_info.format = config->format;
7985 if (config->offload_info.sample_rate == 0)
7986 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007987
Mingming Yin90310102013-11-13 16:57:00 -08007988 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307989 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007990 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007991 ret = -EINVAL;
7992 goto error_open;
7993 }
7994
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007995 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7996 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7997 (audio_extn_passthru_is_passthrough_stream(out)) &&
7998 !((config->sample_rate == 48000) ||
7999 (config->sample_rate == 96000) ||
8000 (config->sample_rate == 192000))) {
8001 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8002 __func__, config->sample_rate, config->offload_info.format);
8003 ret = -EINVAL;
8004 goto error_open;
8005 }
8006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008007 out->compr_config.codec = (struct snd_codec *)
8008 calloc(1, sizeof(struct snd_codec));
8009
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008010 if (!out->compr_config.codec) {
8011 ret = -ENOMEM;
8012 goto error_open;
8013 }
8014
Dhananjay Kumarac341582017-02-23 23:42:25 +05308015 out->stream.pause = out_pause;
8016 out->stream.resume = out_resume;
8017 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308018 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308019 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008020 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308021 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008022 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308023 } else {
8024 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8025 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008026 }
vivek mehta446c3962015-09-14 10:57:35 -07008027
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308028 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8029 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008030#ifdef AUDIO_GKI_ENABLED
8031 /* out->compr_config.codec->reserved[1] is for flags */
8032 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8033#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308034 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008035#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308036 }
8037
vivek mehta446c3962015-09-14 10:57:35 -07008038 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008039 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008040 config->format == 0 && config->sample_rate == 0 &&
8041 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008042 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008043 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8044 } else {
8045 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8046 ret = -EEXIST;
8047 goto error_open;
8048 }
vivek mehta446c3962015-09-14 10:57:35 -07008049 }
8050
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008051 if (config->offload_info.channel_mask)
8052 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008053 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008055 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008056 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308057 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008058 ret = -EINVAL;
8059 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008060 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008061
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008062 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008063 out->sample_rate = config->offload_info.sample_rate;
8064
Mingming Yin3ee55c62014-08-04 14:23:35 -07008065 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008066
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308067 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308068 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308069 audio_extn_dolby_send_ddp_endp_params(adev);
8070 audio_extn_dolby_set_dmid(adev);
8071 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008073 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008074 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008075 out->compr_config.codec->bit_rate =
8076 config->offload_info.bit_rate;
8077 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308078 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008079 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308080 /* Update bit width only for non passthrough usecases.
8081 * For passthrough usecases, the output will always be opened @16 bit
8082 */
8083 if (!audio_extn_passthru_is_passthrough_stream(out))
8084 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308085
8086 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008087#ifdef AUDIO_GKI_ENABLED
8088 /* out->compr_config.codec->reserved[1] is for flags */
8089 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8090 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8091#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308092 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8093 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008094#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308095
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008096 /*TODO: Do we need to change it for passthrough */
8097 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008098
Manish Dewangana6fc5442015-08-24 20:30:31 +05308099 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8100 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308101 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308102 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308103 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8104 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308105
8106 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8107 AUDIO_FORMAT_PCM) {
8108
8109 /*Based on platform support, configure appropriate alsa format for corresponding
8110 *hal input format.
8111 */
8112 out->compr_config.codec->format = hal_format_to_alsa(
8113 config->offload_info.format);
8114
Ashish Jain83a6cc22016-06-28 14:34:17 +05308115 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308116 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308117 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308118
Dhananjay Kumarac341582017-02-23 23:42:25 +05308119 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308120 *hal input format and alsa format might differ based on platform support.
8121 */
8122 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308123 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308124
8125 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8126
Deeraj Soman93155a62019-09-30 19:00:37 +05308127 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8128 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8129 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8130 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8131 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308132
Ashish Jainf1eaa582016-05-23 20:54:24 +05308133 /* Check if alsa session is configured with the same format as HAL input format,
8134 * if not then derive correct fragment size needed to accomodate the
8135 * conversion of HAL input format to alsa format.
8136 */
8137 audio_extn_utils_update_direct_pcm_fragment_size(out);
8138
8139 /*if hal input and output fragment size is different this indicates HAL input format is
8140 *not same as the alsa format
8141 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308142 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308143 /*Allocate a buffer to convert input data to the alsa configured format.
8144 *size of convert buffer is equal to the size required to hold one fragment size
8145 *worth of pcm data, this is because flinger does not write more than fragment_size
8146 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308147 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8148 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308149 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8150 ret = -ENOMEM;
8151 goto error_open;
8152 }
8153 }
8154 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8155 out->compr_config.fragment_size =
8156 audio_extn_passthru_get_buffer_size(&config->offload_info);
8157 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8158 } else {
8159 out->compr_config.fragment_size =
8160 platform_get_compress_offload_buffer_size(&config->offload_info);
8161 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8162 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008163
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308164 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8165 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8166 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008167 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8168#ifdef AUDIO_GKI_ENABLED
8169 generic_dec =
8170 &(out->compr_config.codec->options.generic.reserved[1]);
8171 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8172 AUDIO_OUTPUT_BIT_WIDTH;
8173#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308174 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008175#endif
8176 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008177
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308178 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8179 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8180 }
8181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008182 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8183 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008184
Manish Dewangan69426c82017-01-30 17:35:36 +05308185 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8186 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8187 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8188 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8189 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8190 } else {
8191 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8192 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008193
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308194 memset(&out->channel_map_param, 0,
8195 sizeof(struct audio_out_channel_map_param));
8196
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008197 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308198 out->send_next_track_params = false;
8199 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008200 out->offload_state = OFFLOAD_STATE_IDLE;
8201 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008202 out->writeAt.tv_sec = 0;
8203 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008204
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008205 audio_extn_dts_create_state_notifier_node(out->usecase);
8206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008207 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8208 __func__, config->offload_info.version,
8209 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308210
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308211 /* Check if DSD audio format is supported in codec
8212 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308213 */
8214
8215 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308216 (!platform_check_codec_dsd_support(adev->platform) ||
8217 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308218 ret = -EINVAL;
8219 goto error_open;
8220 }
8221
Ashish Jain5106d362016-05-11 19:23:33 +05308222 /* Disable gapless if any of the following is true
8223 * passthrough playback
8224 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308225 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308226 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308227 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308228 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008229 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308230 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308231 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308232 check_and_set_gapless_mode(adev, false);
8233 } else
8234 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008235
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308236 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008237 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8238 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308239 if (config->format == AUDIO_FORMAT_DSD) {
8240 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008241#ifdef AUDIO_GKI_ENABLED
8242 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8243 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8244#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308245 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008246#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308247 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008248
8249 create_offload_callback_thread(out);
8250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008251 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008252 switch (config->sample_rate) {
8253 case 0:
8254 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8255 break;
8256 case 8000:
8257 case 16000:
8258 case 48000:
8259 out->sample_rate = config->sample_rate;
8260 break;
8261 default:
8262 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8263 config->sample_rate);
8264 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8265 ret = -EINVAL;
8266 goto error_open;
8267 }
8268 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8269 switch (config->channel_mask) {
8270 case AUDIO_CHANNEL_NONE:
8271 case AUDIO_CHANNEL_OUT_STEREO:
8272 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8273 break;
8274 default:
8275 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8276 config->channel_mask);
8277 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8278 ret = -EINVAL;
8279 goto error_open;
8280 }
8281 switch (config->format) {
8282 case AUDIO_FORMAT_DEFAULT:
8283 case AUDIO_FORMAT_PCM_16_BIT:
8284 out->format = AUDIO_FORMAT_PCM_16_BIT;
8285 break;
8286 default:
8287 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8288 config->format);
8289 config->format = AUDIO_FORMAT_PCM_16_BIT;
8290 ret = -EINVAL;
8291 goto error_open;
8292 }
8293
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308294 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008295 if (ret != 0) {
8296 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008297 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008298 goto error_open;
8299 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008300 } else if (is_single_device_type_equal(&out->device_list,
8301 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008302 switch (config->sample_rate) {
8303 case 0:
8304 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8305 break;
8306 case 8000:
8307 case 16000:
8308 case 48000:
8309 out->sample_rate = config->sample_rate;
8310 break;
8311 default:
8312 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8313 config->sample_rate);
8314 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8315 ret = -EINVAL;
8316 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008317 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008318 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8319 switch (config->channel_mask) {
8320 case AUDIO_CHANNEL_NONE:
8321 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8322 break;
8323 case AUDIO_CHANNEL_OUT_STEREO:
8324 out->channel_mask = config->channel_mask;
8325 break;
8326 default:
8327 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8328 config->channel_mask);
8329 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8330 ret = -EINVAL;
8331 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008332 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008333 switch (config->format) {
8334 case AUDIO_FORMAT_DEFAULT:
8335 out->format = AUDIO_FORMAT_PCM_16_BIT;
8336 break;
8337 case AUDIO_FORMAT_PCM_16_BIT:
8338 out->format = config->format;
8339 break;
8340 default:
8341 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8342 config->format);
8343 config->format = AUDIO_FORMAT_PCM_16_BIT;
8344 ret = -EINVAL;
8345 break;
8346 }
8347 if (ret != 0)
8348 goto error_open;
8349
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008350 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8351 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008352 out->config.rate = out->sample_rate;
8353 out->config.channels =
8354 audio_channel_count_from_out_mask(out->channel_mask);
8355 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008356 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008357 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308358 unsigned int channels = 0;
8359 /*Update config params to default if not set by the caller*/
8360 if (config->sample_rate == 0)
8361 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8362 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8363 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8364 if (config->format == AUDIO_FORMAT_DEFAULT)
8365 config->format = AUDIO_FORMAT_PCM_16_BIT;
8366
8367 channels = audio_channel_count_from_out_mask(out->channel_mask);
8368
Varun Balaraje49253e2017-07-06 19:48:56 +05308369 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8370 out->usecase = get_interactive_usecase(adev);
8371 out->config = pcm_config_low_latency;
8372 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308373 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008374 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8375 out->flags);
8376 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008377 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8378 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8379 out->config = pcm_config_mmap_playback;
8380 out->stream.start = out_start;
8381 out->stream.stop = out_stop;
8382 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8383 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308384 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8385 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008386 out->hal_output_suspend_supported =
8387 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8388 out->dynamic_pm_qos_config_supported =
8389 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8390 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008391 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8392 } else {
8393 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8394 //the mixer path will be a string similar to "low-latency-playback resume"
8395 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8396 strlcat(out->pm_qos_mixer_path,
8397 " resume", MAX_MIXER_PATH_LEN);
8398 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8399 out->pm_qos_mixer_path);
8400 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308401 out->config = pcm_config_low_latency;
8402 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8403 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8404 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308405 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8406 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8407 if (out->config.period_size <= 0) {
8408 ALOGE("Invalid configuration period size is not valid");
8409 ret = -EINVAL;
8410 goto error_open;
8411 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008412 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8413 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8414 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008415 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8416 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8417 out->config = pcm_config_haptics_audio;
8418 if (force_haptic_path)
8419 adev->haptics_config = pcm_config_haptics_audio;
8420 else
8421 adev->haptics_config = pcm_config_haptics;
8422
Meng Wangd08ce322020-04-02 08:59:20 +08008423 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008424 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8425
8426 if (force_haptic_path) {
8427 out->config.channels = 1;
8428 adev->haptics_config.channels = 1;
8429 } else
8430 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 -08008431 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008432 ret = audio_extn_auto_hal_open_output_stream(out);
8433 if (ret) {
8434 ALOGE("%s: Failed to open output stream for bus device", __func__);
8435 ret = -EINVAL;
8436 goto error_open;
8437 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308438 } else {
8439 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008440 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8441 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308442 }
8443 out->hal_ip_format = format = out->format;
8444 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8445 out->hal_op_format = pcm_format_to_hal(out->config.format);
8446 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8447 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008448 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308449 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308450 if (out->hal_ip_format != out->hal_op_format) {
8451 uint32_t buffer_size = out->config.period_size *
8452 format_to_bitwidth_table[out->hal_op_format] *
8453 out->config.channels;
8454 out->convert_buffer = calloc(1, buffer_size);
8455 if (out->convert_buffer == NULL){
8456 ALOGE("Allocation failed for convert buffer for size %d",
8457 out->compr_config.fragment_size);
8458 ret = -ENOMEM;
8459 goto error_open;
8460 }
8461 ALOGD("Convert buffer allocated of size %d", buffer_size);
8462 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008463 }
8464
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008465 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8466 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308467
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008468 /* TODO remove this hardcoding and check why width is zero*/
8469 if (out->bit_width == 0)
8470 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308471 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008472 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008473 &out->device_list, out->flags,
8474 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308475 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308476 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008477 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008478 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8479 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008480 if(adev->primary_output == NULL)
8481 adev->primary_output = out;
8482 else {
8483 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008484 ret = -EEXIST;
8485 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008486 }
8487 }
8488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008489 /* Check if this usecase is already existing */
8490 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008491 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8492 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008494 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008495 ret = -EEXIST;
8496 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008497 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008499 pthread_mutex_unlock(&adev->lock);
8500
8501 out->stream.common.get_sample_rate = out_get_sample_rate;
8502 out->stream.common.set_sample_rate = out_set_sample_rate;
8503 out->stream.common.get_buffer_size = out_get_buffer_size;
8504 out->stream.common.get_channels = out_get_channels;
8505 out->stream.common.get_format = out_get_format;
8506 out->stream.common.set_format = out_set_format;
8507 out->stream.common.standby = out_standby;
8508 out->stream.common.dump = out_dump;
8509 out->stream.common.set_parameters = out_set_parameters;
8510 out->stream.common.get_parameters = out_get_parameters;
8511 out->stream.common.add_audio_effect = out_add_audio_effect;
8512 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8513 out->stream.get_latency = out_get_latency;
8514 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008515#ifdef NO_AUDIO_OUT
8516 out->stream.write = out_write_for_no_output;
8517#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008519#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008520 out->stream.get_render_position = out_get_render_position;
8521 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008522 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008523
Haynes Mathew George16081042017-05-31 17:16:49 -07008524 if (out->realtime)
8525 out->af_period_multiplier = af_period_multiplier;
8526 else
8527 out->af_period_multiplier = 1;
8528
Andy Hunga1f48fa2019-07-01 18:14:53 -07008529 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008531 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008532 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008533 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534
8535 config->format = out->stream.common.get_format(&out->stream.common);
8536 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8537 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308538 register_format(out->format, out->supported_formats);
8539 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8540 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008541
Aalique Grahame22e49102018-12-18 14:23:57 -08008542 out->error_log = error_log_create(
8543 ERROR_LOG_ENTRIES,
8544 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8545
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308546 /*
8547 By locking output stream before registering, we allow the callback
8548 to update stream's state only after stream's initial state is set to
8549 adev state.
8550 */
8551 lock_output_stream(out);
8552 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8553 pthread_mutex_lock(&adev->lock);
8554 out->card_status = adev->card_status;
8555 pthread_mutex_unlock(&adev->lock);
8556 pthread_mutex_unlock(&out->lock);
8557
Aalique Grahame22e49102018-12-18 14:23:57 -08008558 stream_app_type_cfg_init(&out->app_type_cfg);
8559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008560 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308561 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008562 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008563
8564 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8565 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8566 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008567 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308568 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008569 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008570 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308571 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8572 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008573 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8574 out->usecase, PCM_PLAYBACK);
8575 hdlr_stream_cfg.flags = out->flags;
8576 hdlr_stream_cfg.type = PCM_PLAYBACK;
8577 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8578 &hdlr_stream_cfg);
8579 if (ret) {
8580 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8581 out->adsp_hdlr_stream_handle = NULL;
8582 }
8583 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308584 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8585 is_direct_passthough, false);
8586 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8587 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008588 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008589 if (ret < 0) {
8590 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8591 out->ip_hdlr_handle = NULL;
8592 }
8593 }
Derek Chenf939fb72018-11-13 13:34:41 -08008594
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008595 ret = io_streams_map_insert(adev, &out->stream.common,
8596 out->handle, AUDIO_PATCH_HANDLE_NONE);
8597 if (ret != 0)
8598 goto error_open;
8599
Derek Chenf939fb72018-11-13 13:34:41 -08008600 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8601 calloc(1, sizeof(streams_output_ctxt_t));
8602 if (out_ctxt == NULL) {
8603 ALOGE("%s fail to allocate output ctxt", __func__);
8604 ret = -ENOMEM;
8605 goto error_open;
8606 }
8607 out_ctxt->output = out;
8608
8609 pthread_mutex_lock(&adev->lock);
8610 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8611 pthread_mutex_unlock(&adev->lock);
8612
Eric Laurent994a6932013-07-17 11:51:42 -07008613 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008614 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008615
8616error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308617 if (out->convert_buffer)
8618 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008619 free(out);
8620 *stream_out = NULL;
8621 ALOGD("%s: exit: ret %d", __func__, ret);
8622 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008623}
8624
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308625void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008626 struct audio_stream_out *stream)
8627{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008628 struct stream_out *out = (struct stream_out *)stream;
8629 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008630 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008631
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008632 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308633
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008634 io_streams_map_remove(adev, out->handle);
8635
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308636 // must deregister from sndmonitor first to prevent races
8637 // between the callback and close_stream
8638 audio_extn_snd_mon_unregister_listener(out);
8639
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008640 /* close adsp hdrl session before standby */
8641 if (out->adsp_hdlr_stream_handle) {
8642 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8643 if (ret)
8644 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8645 out->adsp_hdlr_stream_handle = NULL;
8646 }
8647
Manish Dewangan21a850a2017-08-14 12:03:55 +05308648 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008649 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8650 out->ip_hdlr_handle = NULL;
8651 }
8652
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008653 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308654 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008655 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308656 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308657 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008658 if(ret != 0)
8659 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8660 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008661 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008662 out_standby(&stream->common);
8663
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008664 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008665 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008666 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008667 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008668 if (out->compr_config.codec != NULL)
8669 free(out->compr_config.codec);
8670 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008671
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308672 out->a2dp_compress_mute = false;
8673
Varun Balaraje49253e2017-07-06 19:48:56 +05308674 if (is_interactive_usecase(out->usecase))
8675 free_interactive_usecase(adev, out->usecase);
8676
Ashish Jain83a6cc22016-06-28 14:34:17 +05308677 if (out->convert_buffer != NULL) {
8678 free(out->convert_buffer);
8679 out->convert_buffer = NULL;
8680 }
8681
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008682 if (adev->voice_tx_output == out)
8683 adev->voice_tx_output = NULL;
8684
Aalique Grahame22e49102018-12-18 14:23:57 -08008685 error_log_destroy(out->error_log);
8686 out->error_log = NULL;
8687
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308688 if (adev->primary_output == out)
8689 adev->primary_output = NULL;
8690
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008691 pthread_cond_destroy(&out->cond);
8692 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008693 pthread_mutex_destroy(&out->pre_lock);
8694 pthread_mutex_destroy(&out->latch_lock);
8695 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008696
8697 pthread_mutex_lock(&adev->lock);
8698 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8699 if (out_ctxt != NULL) {
8700 list_remove(&out_ctxt->list);
8701 free(out_ctxt);
8702 } else {
8703 ALOGW("%s, output stream already closed", __func__);
8704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008705 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008706 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008707 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008708}
8709
8710static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8711{
8712 struct audio_device *adev = (struct audio_device *)dev;
8713 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008714 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008715 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008716 int ret;
8717 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008718 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008719 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008720 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008721
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008722 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008723 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008724
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308725 if (!parms)
8726 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308727
Derek Chen6f293672019-04-01 01:40:24 -07008728 /* notify adev and input/output streams on the snd card status */
8729 adev_snd_mon_cb((void *)adev, parms);
8730
8731 list_for_each(node, &adev->active_outputs_list) {
8732 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8733 streams_output_ctxt_t,
8734 list);
8735 out_snd_mon_cb((void *)out_ctxt->output, parms);
8736 }
8737
8738 list_for_each(node, &adev->active_inputs_list) {
8739 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8740 streams_input_ctxt_t,
8741 list);
8742 in_snd_mon_cb((void *)in_ctxt->input, parms);
8743 }
8744
Zhou Songd6d71752019-05-21 18:08:51 +08008745 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308746 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8747 if (ret >= 0) {
8748 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008749 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308750 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008751 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308752 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008753 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008754 }
8755 }
8756
8757 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008758 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008759 if (!strncmp(value, "false", 5) &&
8760 audio_extn_a2dp_source_is_suspended()) {
8761 struct audio_usecase *usecase;
8762 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008763 list_for_each(node, &adev->usecase_list) {
8764 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008765 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008766 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008767 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008768 reassign_device_list(&usecase->stream.in->device_list,
8769 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008770 select_devices(adev, usecase->id);
8771 }
Zhou Songd6d71752019-05-21 18:08:51 +08008772 }
8773 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308774 }
8775
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008776 status = voice_set_parameters(adev, parms);
8777 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008778 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008780 status = platform_set_parameters(adev->platform, parms);
8781 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008782 goto done;
8783
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008784 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8785 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008786 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008787 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8788 adev->bluetooth_nrec = true;
8789 else
8790 adev->bluetooth_nrec = false;
8791 }
8792
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008793 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8794 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008795 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8796 adev->screen_off = false;
8797 else
8798 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008799 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008800 }
8801
Eric Laurent4b084132018-10-19 17:33:43 -07008802 ret = str_parms_get_int(parms, "rotation", &val);
8803 if (ret >= 0) {
8804 bool reverse_speakers = false;
8805 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8806 switch (val) {
8807 // FIXME: note that the code below assumes that the speakers are in the correct placement
8808 // relative to the user when the device is rotated 90deg from its default rotation. This
8809 // assumption is device-specific, not platform-specific like this code.
8810 case 270:
8811 reverse_speakers = true;
8812 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8813 break;
8814 case 0:
8815 case 180:
8816 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8817 break;
8818 case 90:
8819 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8820 break;
8821 default:
8822 ALOGE("%s: unexpected rotation of %d", __func__, val);
8823 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008824 }
Eric Laurent4b084132018-10-19 17:33:43 -07008825 if (status == 0) {
8826 // check and set swap
8827 // - check if orientation changed and speaker active
8828 // - set rotation and cache the rotation value
8829 adev->camera_orientation =
8830 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8831 if (!audio_extn_is_maxx_audio_enabled())
8832 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8833 }
8834 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008835
Mingming Yin514a8bc2014-07-29 15:22:21 -07008836 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8837 if (ret >= 0) {
8838 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8839 adev->bt_wb_speech_enabled = true;
8840 else
8841 adev->bt_wb_speech_enabled = false;
8842 }
8843
Zhou Song12c29502019-03-16 10:37:18 +08008844 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8845 if (ret >= 0) {
8846 val = atoi(value);
8847 adev->swb_speech_mode = val;
8848 }
8849
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008850 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8851 if (ret >= 0) {
8852 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308853 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008854 if (audio_is_output_device(val) &&
8855 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008856 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008857 platform_get_controller_stream_from_params(parms, &controller, &stream);
8858 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8859 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008860 if (ret < 0) {
8861 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308862 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008863 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008864 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308865 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008866 /*
8867 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8868 * Per AudioPolicyManager, USB device is higher priority than WFD.
8869 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8870 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8871 * starting voice call on USB
8872 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008873 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308874 if (ret >= 0)
8875 audio_extn_usb_add_device(device, atoi(value));
8876
Zhou Song6f862822017-11-06 17:27:57 +08008877 if (!audio_extn_usb_is_tunnel_supported()) {
8878 ALOGV("detected USB connect .. disable proxy");
8879 adev->allow_afe_proxy_usage = false;
8880 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008881 }
8882 }
8883
8884 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8885 if (ret >= 0) {
8886 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308887 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008888 /*
8889 * The HDMI / Displayport disconnect handling has been moved to
8890 * audio extension to ensure that its parameters are not
8891 * invalidated prior to updating sysfs of the disconnect event
8892 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8893 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308894 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008895 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308896 if (ret >= 0)
8897 audio_extn_usb_remove_device(device, atoi(value));
8898
Zhou Song6f862822017-11-06 17:27:57 +08008899 if (!audio_extn_usb_is_tunnel_supported()) {
8900 ALOGV("detected USB disconnect .. enable proxy");
8901 adev->allow_afe_proxy_usage = true;
8902 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008903 }
8904 }
8905
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008906 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008907
8908 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008909 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308910 struct audio_usecase *usecase;
8911 struct listnode *node;
8912 list_for_each(node, &adev->usecase_list) {
8913 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008914 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8915 continue;
8916
8917 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308918 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308919 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308920 ALOGD("Switching to speaker and muting the stream before select_devices");
8921 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308922 //force device switch to re configure encoder
8923 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308924 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008925 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308926 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008927 out_set_compr_volume(&usecase->stream.out->stream,
8928 usecase->stream.out->volume_l,
8929 usecase->stream.out->volume_r);
8930 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308931 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308932 break;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008933 } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
8934 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8935 if (usecase->stream.out->a2dp_compress_mute) {
8936 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8937 reassign_device_list(&usecase->stream.out->device_list,
8938 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8939 check_a2dp_restore_l(adev, usecase->stream.out, true);
8940 break;
8941 }
8942 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308943 }
8944 }
8945 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008946
8947 //handle vr audio setparam
8948 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8949 value, sizeof(value));
8950 if (ret >= 0) {
8951 ALOGI("Setting vr mode to be %s", value);
8952 if (!strncmp(value, "true", 4)) {
8953 adev->vr_audio_mode_enabled = true;
8954 ALOGI("Setting vr mode to true");
8955 } else if (!strncmp(value, "false", 5)) {
8956 adev->vr_audio_mode_enabled = false;
8957 ALOGI("Setting vr mode to false");
8958 } else {
8959 ALOGI("wrong vr mode set");
8960 }
8961 }
8962
Eric Laurent4b084132018-10-19 17:33:43 -07008963 //FIXME: to be replaced by proper video capture properties API
8964 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8965 if (ret >= 0) {
8966 int camera_facing = CAMERA_FACING_BACK;
8967 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8968 camera_facing = CAMERA_FACING_FRONT;
8969 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8970 camera_facing = CAMERA_FACING_BACK;
8971 else {
8972 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8973 goto done;
8974 }
8975 adev->camera_orientation =
8976 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8977 struct audio_usecase *usecase;
8978 struct listnode *node;
8979 list_for_each(node, &adev->usecase_list) {
8980 usecase = node_to_item(node, struct audio_usecase, list);
8981 struct stream_in *in = usecase->stream.in;
8982 if (usecase->type == PCM_CAPTURE && in != NULL &&
8983 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8984 select_devices(adev, in->usecase);
8985 }
8986 }
8987 }
8988
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308989 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008990done:
8991 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008992 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308993error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008994 ALOGV("%s: exit with code(%d)", __func__, status);
8995 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996}
8997
8998static char* adev_get_parameters(const struct audio_hw_device *dev,
8999 const char *keys)
9000{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309001 ALOGD("%s:%s", __func__, keys);
9002
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009003 struct audio_device *adev = (struct audio_device *)dev;
9004 struct str_parms *reply = str_parms_create();
9005 struct str_parms *query = str_parms_create_str(keys);
9006 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309007 char value[256] = {0};
9008 int ret = 0;
9009
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009010 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009011 if (reply) {
9012 str_parms_destroy(reply);
9013 }
9014 if (query) {
9015 str_parms_destroy(query);
9016 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009017 ALOGE("adev_get_parameters: failed to create query or reply");
9018 return NULL;
9019 }
9020
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009021 //handle vr audio getparam
9022
9023 ret = str_parms_get_str(query,
9024 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9025 value, sizeof(value));
9026
9027 if (ret >= 0) {
9028 bool vr_audio_enabled = false;
9029 pthread_mutex_lock(&adev->lock);
9030 vr_audio_enabled = adev->vr_audio_mode_enabled;
9031 pthread_mutex_unlock(&adev->lock);
9032
9033 ALOGI("getting vr mode to %d", vr_audio_enabled);
9034
9035 if (vr_audio_enabled) {
9036 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9037 "true");
9038 goto exit;
9039 } else {
9040 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9041 "false");
9042 goto exit;
9043 }
9044 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009045
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009046 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009047 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009048 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009049 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009050 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009051 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309052 pthread_mutex_unlock(&adev->lock);
9053
Naresh Tannirud7205b62014-06-20 02:54:48 +05309054exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009055 str = str_parms_to_str(reply);
9056 str_parms_destroy(query);
9057 str_parms_destroy(reply);
9058
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309059 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009060 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009061}
9062
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009063static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009064{
9065 return 0;
9066}
9067
9068static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9069{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009070 int ret;
9071 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009072
9073 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9074
Haynes Mathew George5191a852013-09-11 14:19:36 -07009075 pthread_mutex_lock(&adev->lock);
9076 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009077 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009078 pthread_mutex_unlock(&adev->lock);
9079 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009080}
9081
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009082static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9083 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009084{
9085 return -ENOSYS;
9086}
9087
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009088static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9089 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009090{
9091 return -ENOSYS;
9092}
9093
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009094static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9095 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009096{
9097 return -ENOSYS;
9098}
9099
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009100static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9101 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009102{
9103 return -ENOSYS;
9104}
9105
9106static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9107{
9108 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009109 struct listnode *node;
9110 struct audio_usecase *usecase = NULL;
9111 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113 pthread_mutex_lock(&adev->lock);
9114 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309115 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9116 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009117 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009118 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309119 adev->current_call_output = adev->primary_output;
9120 voice_start_call(adev);
9121 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009122 (mode == AUDIO_MODE_NORMAL ||
9123 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009124 list_for_each(node, &adev->usecase_list) {
9125 usecase = node_to_item(node, struct audio_usecase, list);
9126 if (usecase->type == VOICE_CALL)
9127 break;
9128 }
9129 if (usecase &&
9130 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9131 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9132 true);
9133 if (ret != 0) {
9134 /* default service interval was successfully updated,
9135 reopen USB backend with new service interval */
9136 check_usecases_codec_backend(adev,
9137 usecase,
9138 usecase->out_snd_device);
9139 }
9140 }
9141
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009142 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009143 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009144 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009145 // restore device for other active usecases after stop call
9146 list_for_each(node, &adev->usecase_list) {
9147 usecase = node_to_item(node, struct audio_usecase, list);
9148 select_devices(adev, usecase->id);
9149 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009151 }
9152 pthread_mutex_unlock(&adev->lock);
9153 return 0;
9154}
9155
9156static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9157{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009158 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009159 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009160
9161 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009162 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009163 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009164
Derek Chend2530072014-11-24 12:39:14 -08009165 if (adev->ext_hw_plugin)
9166 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009167
9168 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009169 pthread_mutex_unlock(&adev->lock);
9170
9171 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172}
9173
9174static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9175{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009176 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009177 return 0;
9178}
9179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009180static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009181 const struct audio_config *config)
9182{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009183 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009184
Aalique Grahame22e49102018-12-18 14:23:57 -08009185 /* Don't know if USB HIFI in this context so use true to be conservative */
9186 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9187 true /*is_usb_hifi */) != 0)
9188 return 0;
9189
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009190 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9191 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009192}
9193
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009194static bool adev_input_allow_hifi_record(struct audio_device *adev,
9195 audio_devices_t devices,
9196 audio_input_flags_t flags,
9197 audio_source_t source) {
9198 const bool allowed = true;
9199
9200 if (!audio_is_usb_in_device(devices))
9201 return !allowed;
9202
9203 switch (flags) {
9204 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009205 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009206 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9207 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009208 default:
9209 return !allowed;
9210 }
9211
9212 switch (source) {
9213 case AUDIO_SOURCE_DEFAULT:
9214 case AUDIO_SOURCE_MIC:
9215 case AUDIO_SOURCE_UNPROCESSED:
9216 break;
9217 default:
9218 return !allowed;
9219 }
9220
9221 switch (adev->mode) {
9222 case 0:
9223 break;
9224 default:
9225 return !allowed;
9226 }
9227
9228 return allowed;
9229}
9230
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009231static int adev_update_voice_comm_input_stream(struct stream_in *in,
9232 struct audio_config *config)
9233{
9234 bool valid_rate = (config->sample_rate == 8000 ||
9235 config->sample_rate == 16000 ||
9236 config->sample_rate == 32000 ||
9237 config->sample_rate == 48000);
9238 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9239
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009240 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009241 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009242 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9243 in->config = default_pcm_config_voip_copp;
9244 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9245 DEFAULT_VOIP_BUF_DURATION_MS,
9246 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009247 } else {
9248 ALOGW("%s No valid input in voip, use defaults"
9249 "sample rate %u, channel mask 0x%X",
9250 __func__, config->sample_rate, in->channel_mask);
9251 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009252 in->config.rate = config->sample_rate;
9253 in->sample_rate = config->sample_rate;
9254 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009255 //XXX needed for voice_extn_compress_voip_open_input_stream
9256 in->config.rate = config->sample_rate;
9257 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309258 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009259 voice_extn_compress_voip_is_active(in->dev)) &&
9260 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9261 valid_rate && valid_ch) {
9262 voice_extn_compress_voip_open_input_stream(in);
9263 // update rate entries to match config from AF
9264 in->config.rate = config->sample_rate;
9265 in->sample_rate = config->sample_rate;
9266 } else {
9267 ALOGW("%s compress voip not active, use defaults", __func__);
9268 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009269 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009270 return 0;
9271}
9272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009273static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009274 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009275 audio_devices_t devices,
9276 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009277 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309278 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009279 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009280 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009281{
9282 struct audio_device *adev = (struct audio_device *)dev;
9283 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009284 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009285 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009286 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309287 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009288 bool is_usb_dev = audio_is_usb_in_device(devices);
9289 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9290 devices,
9291 flags,
9292 source);
Andy Hung94320602018-10-29 18:31:12 -07009293 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9294 " sample_rate %u, channel_mask %#x, format %#x",
9295 __func__, flags, is_usb_dev, may_use_hifi_record,
9296 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309297
kunleizdff872d2018-08-20 14:40:33 +08009298 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009299 is_usb_dev = false;
9300 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9301 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9302 __func__, devices);
9303 }
9304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009305 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009306
9307 if (!(is_usb_dev && may_use_hifi_record)) {
9308 if (config->sample_rate == 0)
9309 config->sample_rate = 48000;
9310 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9311 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9312 if (config->format == AUDIO_FORMAT_DEFAULT)
9313 config->format = AUDIO_FORMAT_PCM_16_BIT;
9314
9315 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9316
Aalique Grahame22e49102018-12-18 14:23:57 -08009317 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9318 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009319 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309320 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009321
Rahul Sharma99770982019-03-06 17:05:26 +05309322 pthread_mutex_lock(&adev->lock);
9323 if (in_get_stream(adev, handle) != NULL) {
9324 ALOGW("%s, input stream already opened", __func__);
9325 ret = -EEXIST;
9326 }
9327 pthread_mutex_unlock(&adev->lock);
9328 if (ret)
9329 return ret;
9330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009331 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009332
9333 if (!in) {
9334 ALOGE("failed to allocate input stream");
9335 return -ENOMEM;
9336 }
9337
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309338 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309339 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9340 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009341 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009342 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009344 in->stream.common.get_sample_rate = in_get_sample_rate;
9345 in->stream.common.set_sample_rate = in_set_sample_rate;
9346 in->stream.common.get_buffer_size = in_get_buffer_size;
9347 in->stream.common.get_channels = in_get_channels;
9348 in->stream.common.get_format = in_get_format;
9349 in->stream.common.set_format = in_set_format;
9350 in->stream.common.standby = in_standby;
9351 in->stream.common.dump = in_dump;
9352 in->stream.common.set_parameters = in_set_parameters;
9353 in->stream.common.get_parameters = in_get_parameters;
9354 in->stream.common.add_audio_effect = in_add_audio_effect;
9355 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9356 in->stream.set_gain = in_set_gain;
9357 in->stream.read = in_read;
9358 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009359 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309360 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009361 in->stream.set_microphone_direction = in_set_microphone_direction;
9362 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009363 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009364
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009365 list_init(&in->device_list);
9366 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009367 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009368 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009369 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009370 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009371 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009372 in->bit_width = 16;
9373 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009374 in->direction = MIC_DIRECTION_UNSPECIFIED;
9375 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009376 list_init(&in->aec_list);
9377 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009378 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009379
Andy Hung94320602018-10-29 18:31:12 -07009380 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009381 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9382 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9383 /* Force channel config requested to mono if incall
9384 record is being requested for only uplink/downlink */
9385 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9386 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9387 ret = -EINVAL;
9388 goto err_open;
9389 }
9390 }
9391
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009392 if (is_usb_dev && may_use_hifi_record) {
9393 /* HiFi record selects an appropriate format, channel, rate combo
9394 depending on sink capabilities*/
9395 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9396 &config->format,
9397 &in->supported_formats[0],
9398 MAX_SUPPORTED_FORMATS,
9399 &config->channel_mask,
9400 &in->supported_channel_masks[0],
9401 MAX_SUPPORTED_CHANNEL_MASKS,
9402 &config->sample_rate,
9403 &in->supported_sample_rates[0],
9404 MAX_SUPPORTED_SAMPLE_RATES);
9405 if (ret != 0) {
9406 ret = -EINVAL;
9407 goto err_open;
9408 }
9409 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009410 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309411 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309412 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9413 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9414 in->config.format = PCM_FORMAT_S32_LE;
9415 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309416 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9417 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9418 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9419 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9420 bool ret_error = false;
9421 in->bit_width = 24;
9422 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9423 from HAL is 24_packed and 8_24
9424 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9425 24_packed return error indicating supported format is 24_packed
9426 *> In case of any other source requesting 24 bit or float return error
9427 indicating format supported is 16 bit only.
9428
9429 on error flinger will retry with supported format passed
9430 */
9431 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9432 (source != AUDIO_SOURCE_CAMCORDER)) {
9433 config->format = AUDIO_FORMAT_PCM_16_BIT;
9434 if (config->sample_rate > 48000)
9435 config->sample_rate = 48000;
9436 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009437 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9438 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309439 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9440 ret_error = true;
9441 }
9442
9443 if (ret_error) {
9444 ret = -EINVAL;
9445 goto err_open;
9446 }
9447 }
9448
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009449 in->channel_mask = config->channel_mask;
9450 in->format = config->format;
9451
9452 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309453
9454 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9455 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9456 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9457 else {
9458 ret = -EINVAL;
9459 goto err_open;
9460 }
9461 }
9462
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009463 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309464 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9465 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009466 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9467 is_low_latency = true;
9468#if LOW_LATENCY_CAPTURE_USE_CASE
9469 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9470#endif
9471 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009472 if (!in->realtime) {
9473 in->config = pcm_config_audio_capture;
9474 frame_size = audio_stream_in_frame_size(&in->stream);
9475 buffer_size = get_input_buffer_size(config->sample_rate,
9476 config->format,
9477 channel_count,
9478 is_low_latency);
9479 in->config.period_size = buffer_size / frame_size;
9480 in->config.rate = config->sample_rate;
9481 in->af_period_multiplier = 1;
9482 } else {
9483 // period size is left untouched for rt mode playback
9484 in->config = pcm_config_audio_capture_rt;
9485 in->af_period_multiplier = af_period_multiplier;
9486 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009487 }
9488
9489 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9490 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9491 in->realtime = 0;
9492 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9493 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009494 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009495 in->stream.start = in_start;
9496 in->stream.stop = in_stop;
9497 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9498 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009499 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009500 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009501 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9502 in->config = pcm_config_audio_capture;
9503 frame_size = audio_stream_in_frame_size(&in->stream);
9504 buffer_size = get_input_buffer_size(config->sample_rate,
9505 config->format,
9506 channel_count,
9507 false /*is_low_latency*/);
9508 in->config.period_size = buffer_size / frame_size;
9509 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009510 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009511 switch (config->format) {
9512 case AUDIO_FORMAT_PCM_32_BIT:
9513 in->bit_width = 32;
9514 break;
9515 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9516 case AUDIO_FORMAT_PCM_8_24_BIT:
9517 in->bit_width = 24;
9518 break;
9519 default:
9520 in->bit_width = 16;
9521 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009522 } else if (is_single_device_type_equal(&in->device_list,
9523 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9524 is_single_device_type_equal(&in->device_list,
9525 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009526 if (config->sample_rate == 0)
9527 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9528 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9529 config->sample_rate != 8000) {
9530 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9531 ret = -EINVAL;
9532 goto err_open;
9533 }
9534 if (config->format == AUDIO_FORMAT_DEFAULT)
9535 config->format = AUDIO_FORMAT_PCM_16_BIT;
9536 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9537 config->format = AUDIO_FORMAT_PCM_16_BIT;
9538 ret = -EINVAL;
9539 goto err_open;
9540 }
9541
9542 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009543 if (adev->ha_proxy_enable &&
9544 is_single_device_type_equal(&in->device_list,
9545 AUDIO_DEVICE_IN_TELEPHONY_RX))
9546 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009547 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009548 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009549 in->af_period_multiplier = 1;
9550 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9551 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9552 (config->sample_rate == 8000 ||
9553 config->sample_rate == 16000 ||
9554 config->sample_rate == 32000 ||
9555 config->sample_rate == 48000) &&
9556 channel_count == 1) {
9557 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9558 in->config = pcm_config_audio_capture;
9559 frame_size = audio_stream_in_frame_size(&in->stream);
9560 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9561 config->sample_rate,
9562 config->format,
9563 channel_count, false /*is_low_latency*/);
9564 in->config.period_size = buffer_size / frame_size;
9565 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9566 in->config.rate = config->sample_rate;
9567 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009568 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309569 int ret_val;
9570 pthread_mutex_lock(&adev->lock);
9571 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9572 in, config, &channel_mask_updated);
9573 pthread_mutex_unlock(&adev->lock);
9574
9575 if (!ret_val) {
9576 if (channel_mask_updated == true) {
9577 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9578 __func__, config->channel_mask);
9579 ret = -EINVAL;
9580 goto err_open;
9581 }
9582 ALOGD("%s: created multi-channel session succesfully",__func__);
9583 } else if (audio_extn_compr_cap_enabled() &&
9584 audio_extn_compr_cap_format_supported(config->format) &&
9585 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9586 audio_extn_compr_cap_init(in);
9587 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309588 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309589 if (ret)
9590 goto err_open;
9591 } else {
9592 in->config = pcm_config_audio_capture;
9593 in->config.rate = config->sample_rate;
9594 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309595 in->format = config->format;
9596 frame_size = audio_stream_in_frame_size(&in->stream);
9597 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009598 config->format,
9599 channel_count,
9600 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009601 /* prevent division-by-zero */
9602 if (frame_size == 0) {
9603 ALOGE("%s: Error frame_size==0", __func__);
9604 ret = -EINVAL;
9605 goto err_open;
9606 }
9607
Revathi Uddarajud2634032017-12-07 14:42:34 +05309608 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009609 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009610
Revathi Uddarajud2634032017-12-07 14:42:34 +05309611 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9612 /* optionally use VOIP usecase depending on config(s) */
9613 ret = adev_update_voice_comm_input_stream(in, config);
9614 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009615
Revathi Uddarajud2634032017-12-07 14:42:34 +05309616 if (ret) {
9617 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9618 goto err_open;
9619 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009620 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309621
9622 /* assign concurrent capture usecase if record has to caried out from
9623 * actual hardware input source */
9624 if (audio_extn_is_concurrent_capture_enabled() &&
9625 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309626 /* Acquire lock to avoid two concurrent use cases initialized to
9627 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009628
Samyak Jainc37062f2019-04-25 18:41:06 +05309629 if (in->usecase == USECASE_AUDIO_RECORD) {
9630 pthread_mutex_lock(&adev->lock);
9631 if (!(adev->pcm_record_uc_state)) {
9632 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9633 adev->pcm_record_uc_state = 1;
9634 pthread_mutex_unlock(&adev->lock);
9635 } else {
9636 pthread_mutex_unlock(&adev->lock);
9637 /* Assign compress record use case for second record */
9638 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9639 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9640 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9641 if (audio_extn_cin_applicable_stream(in)) {
9642 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309643 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309644 if (ret)
9645 goto err_open;
9646 }
9647 }
9648 }
kunleiz28c73e72019-03-27 17:24:04 +08009649 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009650 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309651 if (audio_extn_ssr_get_stream() != in)
9652 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009653
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009654 in->sample_rate = in->config.rate;
9655
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309656 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9657 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009658 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009659 in->sample_rate, in->bit_width,
9660 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309661 register_format(in->format, in->supported_formats);
9662 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9663 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309664
Aalique Grahame22e49102018-12-18 14:23:57 -08009665 in->error_log = error_log_create(
9666 ERROR_LOG_ENTRIES,
9667 1000000000 /* aggregate consecutive identical errors within one second */);
9668
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009669 /* This stream could be for sound trigger lab,
9670 get sound trigger pcm if present */
9671 audio_extn_sound_trigger_check_and_get_session(in);
9672
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309673 lock_input_stream(in);
9674 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9675 pthread_mutex_lock(&adev->lock);
9676 in->card_status = adev->card_status;
9677 pthread_mutex_unlock(&adev->lock);
9678 pthread_mutex_unlock(&in->lock);
9679
Aalique Grahame22e49102018-12-18 14:23:57 -08009680 stream_app_type_cfg_init(&in->app_type_cfg);
9681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009682 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009683
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009684 ret = io_streams_map_insert(adev, &in->stream.common,
9685 handle, AUDIO_PATCH_HANDLE_NONE);
9686 if (ret != 0)
9687 goto err_open;
9688
Derek Chenf939fb72018-11-13 13:34:41 -08009689 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9690 calloc(1, sizeof(streams_input_ctxt_t));
9691 if (in_ctxt == NULL) {
9692 ALOGE("%s fail to allocate input ctxt", __func__);
9693 ret = -ENOMEM;
9694 goto err_open;
9695 }
9696 in_ctxt->input = in;
9697
9698 pthread_mutex_lock(&adev->lock);
9699 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9700 pthread_mutex_unlock(&adev->lock);
9701
Eric Laurent994a6932013-07-17 11:51:42 -07009702 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009703 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009704
9705err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309706 if (in->usecase == USECASE_AUDIO_RECORD) {
9707 pthread_mutex_lock(&adev->lock);
9708 adev->pcm_record_uc_state = 0;
9709 pthread_mutex_unlock(&adev->lock);
9710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009711 free(in);
9712 *stream_in = NULL;
9713 return ret;
9714}
9715
9716static void adev_close_input_stream(struct audio_hw_device *dev,
9717 struct audio_stream_in *stream)
9718{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009719 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009720 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009721 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309722
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309723 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009724
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009725 if (in == NULL) {
9726 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9727 return;
9728 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009729 io_streams_map_remove(adev, in->capture_handle);
9730
kunleiz70e57612018-12-28 17:50:23 +08009731 /* must deregister from sndmonitor first to prevent races
9732 * between the callback and close_stream
9733 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309734 audio_extn_snd_mon_unregister_listener(stream);
9735
kunleiz70e57612018-12-28 17:50:23 +08009736 /* Disable echo reference if there are no active input, hfp call
9737 * and sound trigger while closing input stream
9738 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009739 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009740 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009741 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9742 struct listnode out_devices;
9743 list_init(&out_devices);
9744 platform_set_echo_reference(adev, false, &out_devices);
9745 } else
kunleiz70e57612018-12-28 17:50:23 +08009746 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309747
Weiyin Jiang2995f662019-04-17 14:25:12 +08009748 error_log_destroy(in->error_log);
9749 in->error_log = NULL;
9750
Pallavid7c7a272018-01-16 11:22:55 +05309751
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009752 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309753 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009754 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309755 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009756 if (ret != 0)
9757 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9758 __func__, ret);
9759 } else
9760 in_standby(&stream->common);
9761
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009762 pthread_mutex_destroy(&in->lock);
9763 pthread_mutex_destroy(&in->pre_lock);
9764
Revathi Uddarajud2634032017-12-07 14:42:34 +05309765 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309766 if (in->usecase == USECASE_AUDIO_RECORD) {
9767 adev->pcm_record_uc_state = 0;
9768 }
9769
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009770 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9771 adev->enable_voicerx = false;
9772 }
9773
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009774 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009775 audio_extn_ssr_deinit();
9776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009777
Garmond Leunge2433c32017-09-28 21:51:22 -07009778 if (audio_extn_ffv_get_stream() == in) {
9779 audio_extn_ffv_stream_deinit();
9780 }
9781
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309782 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009783 audio_extn_compr_cap_format_supported(in->config.format))
9784 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309785
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309786 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309787 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009788
Mingming Yinfd7607b2016-01-22 12:48:44 -08009789 if (in->is_st_session) {
9790 ALOGV("%s: sound trigger pcm stop lab", __func__);
9791 audio_extn_sound_trigger_stop_lab(in);
9792 }
Derek Chenf939fb72018-11-13 13:34:41 -08009793 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9794 if (in_ctxt != NULL) {
9795 list_remove(&in_ctxt->list);
9796 free(in_ctxt);
9797 } else {
9798 ALOGW("%s, input stream already closed", __func__);
9799 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009800 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009802 return;
9803}
9804
Aalique Grahame22e49102018-12-18 14:23:57 -08009805/* verifies input and output devices and their capabilities.
9806 *
9807 * This verification is required when enabling extended bit-depth or
9808 * sampling rates, as not all qcom products support it.
9809 *
9810 * Suitable for calling only on initialization such as adev_open().
9811 * It fills the audio_device use_case_table[] array.
9812 *
9813 * Has a side-effect that it needs to configure audio routing / devices
9814 * in order to power up the devices and read the device parameters.
9815 * It does not acquire any hw device lock. Should restore the devices
9816 * back to "normal state" upon completion.
9817 */
9818static int adev_verify_devices(struct audio_device *adev)
9819{
9820 /* enumeration is a bit difficult because one really wants to pull
9821 * the use_case, device id, etc from the hidden pcm_device_table[].
9822 * In this case there are the following use cases and device ids.
9823 *
9824 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9825 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9826 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9827 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9828 * [USECASE_AUDIO_RECORD] = {0, 0},
9829 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9830 * [USECASE_VOICE_CALL] = {2, 2},
9831 *
9832 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9833 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9834 */
9835
9836 /* should be the usecases enabled in adev_open_input_stream() */
9837 static const int test_in_usecases[] = {
9838 USECASE_AUDIO_RECORD,
9839 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9840 };
9841 /* should be the usecases enabled in adev_open_output_stream()*/
9842 static const int test_out_usecases[] = {
9843 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9844 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9845 };
9846 static const usecase_type_t usecase_type_by_dir[] = {
9847 PCM_PLAYBACK,
9848 PCM_CAPTURE,
9849 };
9850 static const unsigned flags_by_dir[] = {
9851 PCM_OUT,
9852 PCM_IN,
9853 };
9854
9855 size_t i;
9856 unsigned dir;
9857 const unsigned card_id = adev->snd_card;
9858
9859 for (dir = 0; dir < 2; ++dir) {
9860 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9861 const unsigned flags_dir = flags_by_dir[dir];
9862 const size_t testsize =
9863 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9864 const int *testcases =
9865 dir ? test_in_usecases : test_out_usecases;
9866 const audio_devices_t audio_device =
9867 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9868
9869 for (i = 0; i < testsize; ++i) {
9870 const audio_usecase_t audio_usecase = testcases[i];
9871 int device_id;
9872 struct pcm_params **pparams;
9873 struct stream_out out;
9874 struct stream_in in;
9875 struct audio_usecase uc_info;
9876 int retval;
9877
9878 pparams = &adev->use_case_table[audio_usecase];
9879 pcm_params_free(*pparams); /* can accept null input */
9880 *pparams = NULL;
9881
9882 /* find the device ID for the use case (signed, for error) */
9883 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9884 if (device_id < 0)
9885 continue;
9886
9887 /* prepare structures for device probing */
9888 memset(&uc_info, 0, sizeof(uc_info));
9889 uc_info.id = audio_usecase;
9890 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009891 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009892 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009893 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009894 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009895 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009896 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9897 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009898 }
9899 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009900 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009901 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009902 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009903 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009904 uc_info.in_snd_device = SND_DEVICE_NONE;
9905 uc_info.out_snd_device = SND_DEVICE_NONE;
9906 list_add_tail(&adev->usecase_list, &uc_info.list);
9907
9908 /* select device - similar to start_(in/out)put_stream() */
9909 retval = select_devices(adev, audio_usecase);
9910 if (retval >= 0) {
9911 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9912#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009913 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009914 if (*pparams) {
9915 ALOGV("%s: (%s) card %d device %d", __func__,
9916 dir ? "input" : "output", card_id, device_id);
9917 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9918 } else {
9919 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9920 }
9921#endif
9922 }
9923
9924 /* deselect device - similar to stop_(in/out)put_stream() */
9925 /* 1. Get and set stream specific mixer controls */
9926 retval = disable_audio_route(adev, &uc_info);
9927 /* 2. Disable the rx device */
9928 retval = disable_snd_device(adev,
9929 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9930 list_remove(&uc_info.list);
9931 }
9932 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009933 return 0;
9934}
9935
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009936int update_patch(unsigned int num_sources,
9937 const struct audio_port_config *sources,
9938 unsigned int num_sinks,
9939 const struct audio_port_config *sinks,
9940 audio_patch_handle_t handle,
9941 struct audio_patch_info *p_info,
9942 patch_type_t patch_type, bool new_patch)
9943{
9944 ALOGD("%s: enter", __func__);
9945
9946 if (p_info == NULL) {
9947 ALOGE("%s: Invalid patch pointer", __func__);
9948 return -EINVAL;
9949 }
9950
9951 if (new_patch) {
9952 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9953 if (p_info->patch == NULL) {
9954 ALOGE("%s: Could not allocate patch", __func__);
9955 return -ENOMEM;
9956 }
9957 }
9958
9959 p_info->patch->id = handle;
9960 p_info->patch->num_sources = num_sources;
9961 p_info->patch->num_sinks = num_sinks;
9962
9963 for (int i = 0; i < num_sources; i++)
9964 p_info->patch->sources[i] = sources[i];
9965 for (int i = 0; i < num_sinks; i++)
9966 p_info->patch->sinks[i] = sinks[i];
9967
9968 p_info->patch_type = patch_type;
9969 return 0;
9970}
9971
9972audio_patch_handle_t generate_patch_handle()
9973{
9974 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9975 if (++patch_handle < 0)
9976 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9977 return patch_handle;
9978}
9979
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309980int adev_create_audio_patch(struct audio_hw_device *dev,
9981 unsigned int num_sources,
9982 const struct audio_port_config *sources,
9983 unsigned int num_sinks,
9984 const struct audio_port_config *sinks,
9985 audio_patch_handle_t *handle)
9986{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009987 int ret = 0;
9988 struct audio_device *adev = (struct audio_device *)dev;
9989 struct audio_patch_info *p_info = NULL;
9990 patch_type_t patch_type = PATCH_NONE;
9991 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9992 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9993 struct audio_stream_info *s_info = NULL;
9994 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009995 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009996 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9997 bool new_patch = false;
9998 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309999
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010000 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10001 num_sources, num_sinks, *handle);
10002
10003 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10004 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10005 ALOGE("%s: Invalid patch arguments", __func__);
10006 ret = -EINVAL;
10007 goto done;
10008 }
10009
10010 if (num_sources > 1) {
10011 ALOGE("%s: Multiple sources are not supported", __func__);
10012 ret = -EINVAL;
10013 goto done;
10014 }
10015
10016 if (sources == NULL || sinks == NULL) {
10017 ALOGE("%s: Invalid sources or sinks port config", __func__);
10018 ret = -EINVAL;
10019 goto done;
10020 }
10021
10022 ALOGV("%s: source role %d, source type %d", __func__,
10023 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010024 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025
10026 // Populate source/sink information and fetch stream info
10027 switch (sources[0].type) {
10028 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10029 device_type = sources[0].ext.device.type;
10030 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010031 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10033 patch_type = PATCH_CAPTURE;
10034 io_handle = sinks[0].ext.mix.handle;
10035 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010036 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037 __func__, device_type, io_handle);
10038 } else {
10039 // Device to device patch is not implemented.
10040 // This space will need changes if audio HAL
10041 // handles device to device patches in the future.
10042 patch_type = PATCH_DEVICE_LOOPBACK;
10043 }
10044 break;
10045 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10046 io_handle = sources[0].ext.mix.handle;
10047 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010048 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010050 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 }
10052 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010053 ALOGD("%s: Playback patch from mix handle %d to device %x",
10054 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010055 break;
10056 case AUDIO_PORT_TYPE_SESSION:
10057 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010058 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10059 ret = -EINVAL;
10060 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010061 }
10062
10063 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010064
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010065 // Generate patch info and update patch
10066 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010067 *handle = generate_patch_handle();
10068 p_info = (struct audio_patch_info *)
10069 calloc(1, sizeof(struct audio_patch_info));
10070 if (p_info == NULL) {
10071 ALOGE("%s: Failed to allocate memory", __func__);
10072 pthread_mutex_unlock(&adev->lock);
10073 ret = -ENOMEM;
10074 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010076 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010077 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010078 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079 if (p_info == NULL) {
10080 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10081 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010082 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 ret = -EINVAL;
10084 goto done;
10085 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010087 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010088 *handle, p_info, patch_type, new_patch);
10089
10090 // Fetch stream info of associated mix for playback or capture patches
10091 if (p_info->patch_type == PATCH_PLAYBACK ||
10092 p_info->patch_type == PATCH_CAPTURE) {
10093 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10094 if (s_info == NULL) {
10095 ALOGE("%s: Failed to obtain stream info", __func__);
10096 if (new_patch)
10097 free(p_info);
10098 pthread_mutex_unlock(&adev->lock);
10099 ret = -EINVAL;
10100 goto done;
10101 }
10102 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10103 s_info->patch_handle = *handle;
10104 stream = s_info->stream;
10105 }
10106 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107
10108 // Update routing for stream
10109 if (stream != NULL) {
10110 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010111 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010112 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010113 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010114 if (ret < 0) {
10115 pthread_mutex_lock(&adev->lock);
10116 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10117 if (new_patch)
10118 free(p_info);
10119 pthread_mutex_unlock(&adev->lock);
10120 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10121 goto done;
10122 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010123 }
10124
10125 // Add new patch to patch map
10126 if (!ret && new_patch) {
10127 pthread_mutex_lock(&adev->lock);
10128 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010130 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010131 }
10132
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010133done:
10134 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010135 num_sources,
10136 sources,
10137 num_sinks,
10138 sinks,
10139 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010141 num_sources,
10142 sources,
10143 num_sinks,
10144 sinks,
10145 handle);
10146 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010147}
10148
10149int adev_release_audio_patch(struct audio_hw_device *dev,
10150 audio_patch_handle_t handle)
10151{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 struct audio_device *adev = (struct audio_device *) dev;
10153 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010154 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010155 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010156
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010157 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10158 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10159 ret = -EINVAL;
10160 goto done;
10161 }
10162
10163 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010164 pthread_mutex_lock(&adev->lock);
10165 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010166 if (p_info == NULL) {
10167 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010168 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 ret = -EINVAL;
10170 goto done;
10171 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010172 struct audio_patch *patch = p_info->patch;
10173 if (patch == NULL) {
10174 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010175 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010176 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010177 goto done;
10178 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010179 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10180 switch (patch->sources[0].type) {
10181 case AUDIO_PORT_TYPE_MIX:
10182 io_handle = patch->sources[0].ext.mix.handle;
10183 break;
10184 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010185 if (p_info->patch_type == PATCH_CAPTURE)
10186 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 break;
10188 case AUDIO_PORT_TYPE_SESSION:
10189 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010190 pthread_mutex_unlock(&adev->lock);
10191 ret = -EINVAL;
10192 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010193 }
10194
10195 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010196 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010197 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010198 if (patch_type == PATCH_PLAYBACK ||
10199 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010200 struct audio_stream_info *s_info =
10201 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10202 if (s_info == NULL) {
10203 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10204 pthread_mutex_unlock(&adev->lock);
10205 goto done;
10206 }
10207 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10208 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010209 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010210 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010213 struct listnode devices;
10214 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010215 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010216 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010217 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010218 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 }
10220
10221 if (ret < 0)
10222 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10223
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010224done:
10225 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10226 audio_extn_auto_hal_release_audio_patch(dev, handle);
10227
10228 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010229 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010230}
10231
10232int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10233{
Derek Chenf13dd492018-11-13 14:53:51 -080010234 int ret = 0;
10235
10236 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10237 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10238 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010239}
10240
10241int adev_set_audio_port_config(struct audio_hw_device *dev,
10242 const struct audio_port_config *config)
10243{
Derek Chenf13dd492018-11-13 14:53:51 -080010244 int ret = 0;
10245
10246 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10247 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10248 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010249}
10250
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010251static int adev_dump(const audio_hw_device_t *device __unused,
10252 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010253{
10254 return 0;
10255}
10256
10257static int adev_close(hw_device_t *device)
10258{
Aalique Grahame22e49102018-12-18 14:23:57 -080010259 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010260 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010261
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010262 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010263 return 0;
10264
10265 pthread_mutex_lock(&adev_init_lock);
10266
10267 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010268 if (audio_extn_spkr_prot_is_enabled())
10269 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010270 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010271 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010272 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010273 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010274 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010275 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010276 audio_extn_utils_release_streams_cfg_lists(
10277 &adev->streams_output_cfg_list,
10278 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010279 if (audio_extn_qap_is_enabled())
10280 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010281 if (audio_extn_qaf_is_enabled())
10282 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010283 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010284 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010285 free(adev->snd_dev_ref_cnt);
10286 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010287 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10288 pcm_params_free(adev->use_case_table[i]);
10289 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010290 if (adev->adm_deinit)
10291 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010292 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010293 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010294 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010295 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010296 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010297 if (adev->device_cfg_params) {
10298 free(adev->device_cfg_params);
10299 adev->device_cfg_params = NULL;
10300 }
Derek Chend2530072014-11-24 12:39:14 -080010301 if(adev->ext_hw_plugin)
10302 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010303 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010304 free_map(adev->patch_map);
10305 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010306 free(device);
10307 adev = NULL;
10308 }
10309 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010310 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010311 return 0;
10312}
10313
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010314/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10315 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10316 * just that it _might_ work.
10317 */
10318static int period_size_is_plausible_for_low_latency(int period_size)
10319{
10320 switch (period_size) {
10321 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010322 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010323 case 240:
10324 case 320:
10325 case 480:
10326 return 1;
10327 default:
10328 return 0;
10329 }
10330}
10331
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010332static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10333{
10334 bool is_snd_card_status = false;
10335 bool is_ext_device_status = false;
10336 char value[32];
10337 int card = -1;
10338 card_status_t status;
10339
10340 if (cookie != adev || !parms)
10341 return;
10342
10343 if (!parse_snd_card_status(parms, &card, &status)) {
10344 is_snd_card_status = true;
10345 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10346 is_ext_device_status = true;
10347 } else {
10348 // not a valid event
10349 return;
10350 }
10351
10352 pthread_mutex_lock(&adev->lock);
10353 if (card == adev->snd_card || is_ext_device_status) {
10354 if (is_snd_card_status && adev->card_status != status) {
10355 adev->card_status = status;
10356 platform_snd_card_update(adev->platform, status);
10357 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010358 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010359 if (status == CARD_STATUS_OFFLINE)
10360 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010361 } else if (is_ext_device_status) {
10362 platform_set_parameters(adev->platform, parms);
10363 }
10364 }
10365 pthread_mutex_unlock(&adev->lock);
10366 return;
10367}
10368
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010369/* adev lock held */
10370int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010371{
10372 struct audio_usecase *uc_info;
10373 float left_p;
10374 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010375 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010376
10377 uc_info = get_usecase_from_list(adev, out->usecase);
10378 if (uc_info == NULL) {
10379 ALOGE("%s: Could not find the usecase (%d) in the list",
10380 __func__, out->usecase);
10381 return -EINVAL;
10382 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010383 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010384
10385 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10386 out->usecase, use_case_table[out->usecase]);
10387
10388 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010389 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010391 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010392 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010393 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10394 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010395 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010396 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10397 if (out->a2dp_compress_mute) {
10398 out->a2dp_compress_mute = false;
10399 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10400 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010401 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010402 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010403 out->muted = false;
10404 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010405 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010406 pthread_mutex_lock(&out->latch_lock);
Zhou Songc576a452019-09-09 14:17:40 +080010407 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10408 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010409 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010410 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010411 assign_devices(&devices, &out->device_list);
10412 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010413 left_p = out->volume_l;
10414 right_p = out->volume_r;
10415 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10416 compress_pause(out->compr);
10417 out_set_compr_volume(&out->stream, (float)0, (float)0);
10418 out->a2dp_compress_mute = true;
10419 select_devices(adev, out->usecase);
10420 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10421 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010422 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010423 out->volume_l = left_p;
10424 out->volume_r = right_p;
10425 }
Zhou Songc576a452019-09-09 14:17:40 +080010426 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010427 // mute for non offloaded streams
10428 if (audio_extn_a2dp_source_is_suspended()) {
10429 out->muted = true;
10430 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010431 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010432 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010433 }
10434 ALOGV("%s: exit", __func__);
10435 return 0;
10436}
10437
Haynes Mathew George01156f92018-04-13 15:29:54 -070010438void adev_on_battery_status_changed(bool charging)
10439{
10440 pthread_mutex_lock(&adev->lock);
10441 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10442 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010443 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010444 pthread_mutex_unlock(&adev->lock);
10445}
10446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010447static int adev_open(const hw_module_t *module, const char *name,
10448 hw_device_t **device)
10449{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010450 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010451 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010452 char mixer_ctl_name[128] = {0};
10453 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010454
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010455 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010456 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10457
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010458 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010459 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010460 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010461 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010462 ALOGD("%s: returning existing instance of adev", __func__);
10463 ALOGD("%s: exit", __func__);
10464 pthread_mutex_unlock(&adev_init_lock);
10465 return 0;
10466 }
10467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010468 adev = calloc(1, sizeof(struct audio_device));
10469
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010470 if (!adev) {
10471 pthread_mutex_unlock(&adev_init_lock);
10472 return -ENOMEM;
10473 }
10474
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010475 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10476
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010477 // register audio ext hidl at the earliest
10478 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010479#ifdef DYNAMIC_LOG_ENABLED
10480 register_for_dynamic_logging("hal");
10481#endif
10482
Derek Chenf939fb72018-11-13 13:34:41 -080010483 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010484 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010485 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10486 maj_version = atoi(value);
10487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010488 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010489 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010490 adev->device.common.module = (struct hw_module_t *)module;
10491 adev->device.common.close = adev_close;
10492
10493 adev->device.init_check = adev_init_check;
10494 adev->device.set_voice_volume = adev_set_voice_volume;
10495 adev->device.set_master_volume = adev_set_master_volume;
10496 adev->device.get_master_volume = adev_get_master_volume;
10497 adev->device.set_master_mute = adev_set_master_mute;
10498 adev->device.get_master_mute = adev_get_master_mute;
10499 adev->device.set_mode = adev_set_mode;
10500 adev->device.set_mic_mute = adev_set_mic_mute;
10501 adev->device.get_mic_mute = adev_get_mic_mute;
10502 adev->device.set_parameters = adev_set_parameters;
10503 adev->device.get_parameters = adev_get_parameters;
10504 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10505 adev->device.open_output_stream = adev_open_output_stream;
10506 adev->device.close_output_stream = adev_close_output_stream;
10507 adev->device.open_input_stream = adev_open_input_stream;
10508 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010509 adev->device.create_audio_patch = adev_create_audio_patch;
10510 adev->device.release_audio_patch = adev_release_audio_patch;
10511 adev->device.get_audio_port = adev_get_audio_port;
10512 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010513 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010514 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010515
10516 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010517 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010518 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010519 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010520 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010521 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010522 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010523 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010524 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010525 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010526 /* Init audio and voice feature */
10527 audio_extn_feature_init();
10528 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010529 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010530 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010531 list_init(&adev->active_inputs_list);
10532 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010533 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010534 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10535 audio_extn_utils_hash_eq);
10536 if (!adev->io_streams_map) {
10537 ALOGE("%s: Could not create io streams map", __func__);
10538 ret = -ENOMEM;
10539 goto adev_open_err;
10540 }
10541 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10542 audio_extn_utils_hash_eq);
10543 if (!adev->patch_map) {
10544 ALOGE("%s: Could not create audio patch map", __func__);
10545 ret = -ENOMEM;
10546 goto adev_open_err;
10547 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010548 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010549 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010550 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010551 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010552 adev->perf_lock_opts[0] = 0x101;
10553 adev->perf_lock_opts[1] = 0x20E;
10554 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010555 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010556 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010557 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010558 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010559 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010560
Zhou Song68ebc352019-12-05 17:11:15 +080010561 audio_extn_perf_lock_init();
10562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010563 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010564 adev->platform = platform_init(adev);
10565 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010566 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010567 ret = -EINVAL;
10568 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010569 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010570
Aalique Grahame22e49102018-12-18 14:23:57 -080010571 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010572 if (audio_extn_qap_is_enabled()) {
10573 ret = audio_extn_qap_init(adev);
10574 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010575 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010576 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010577 }
10578 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10579 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10580 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010581
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010582 if (audio_extn_qaf_is_enabled()) {
10583 ret = audio_extn_qaf_init(adev);
10584 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010585 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010586 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010587 }
10588
10589 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10590 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10591 }
10592
Derek Chenae7b0342019-02-08 15:17:04 -080010593 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010594 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10595
Eric Laurentc4aef752013-09-12 17:45:53 -070010596 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10597 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10598 if (adev->visualizer_lib == NULL) {
10599 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10600 } else {
10601 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10602 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010603 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010604 "visualizer_hal_start_output");
10605 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010606 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010607 "visualizer_hal_stop_output");
10608 }
10609 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010610 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010611 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010612 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010613 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010614 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010615 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010616
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010617 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10618 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10619 if (adev->offload_effects_lib == NULL) {
10620 ALOGE("%s: DLOPEN failed for %s", __func__,
10621 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10622 } else {
10623 ALOGV("%s: DLOPEN successful for %s", __func__,
10624 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10625 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010626 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010627 "offload_effects_bundle_hal_start_output");
10628 adev->offload_effects_stop_output =
10629 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10630 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010631 adev->offload_effects_set_hpx_state =
10632 (int (*)(bool))dlsym(adev->offload_effects_lib,
10633 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010634 adev->offload_effects_get_parameters =
10635 (void (*)(struct str_parms *, struct str_parms *))
10636 dlsym(adev->offload_effects_lib,
10637 "offload_effects_bundle_get_parameters");
10638 adev->offload_effects_set_parameters =
10639 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10640 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010641 }
10642 }
10643
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010644 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10645 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10646 if (adev->adm_lib == NULL) {
10647 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10648 } else {
10649 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10650 adev->adm_init = (adm_init_t)
10651 dlsym(adev->adm_lib, "adm_init");
10652 adev->adm_deinit = (adm_deinit_t)
10653 dlsym(adev->adm_lib, "adm_deinit");
10654 adev->adm_register_input_stream = (adm_register_input_stream_t)
10655 dlsym(adev->adm_lib, "adm_register_input_stream");
10656 adev->adm_register_output_stream = (adm_register_output_stream_t)
10657 dlsym(adev->adm_lib, "adm_register_output_stream");
10658 adev->adm_deregister_stream = (adm_deregister_stream_t)
10659 dlsym(adev->adm_lib, "adm_deregister_stream");
10660 adev->adm_request_focus = (adm_request_focus_t)
10661 dlsym(adev->adm_lib, "adm_request_focus");
10662 adev->adm_abandon_focus = (adm_abandon_focus_t)
10663 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010664 adev->adm_set_config = (adm_set_config_t)
10665 dlsym(adev->adm_lib, "adm_set_config");
10666 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10667 dlsym(adev->adm_lib, "adm_request_focus_v2");
10668 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10669 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10670 adev->adm_on_routing_change = (adm_on_routing_change_t)
10671 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010672 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10673 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010674 }
10675 }
10676
Aalique Grahame22e49102018-12-18 14:23:57 -080010677 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010678 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010679 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010680 //initialize this to false for now,
10681 //this will be set to true through set param
10682 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010683
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010684 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010685 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010686
10687 if (k_enable_extended_precision)
10688 adev_verify_devices(adev);
10689
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010690 adev->dsp_bit_width_enforce_mode =
10691 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010692
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010693 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10694 &adev->streams_output_cfg_list,
10695 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010696
Kiran Kandi910e1862013-10-29 13:29:42 -070010697 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010698
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010699 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010700 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010701 trial = atoi(value);
10702 if (period_size_is_plausible_for_low_latency(trial)) {
10703 pcm_config_low_latency.period_size = trial;
10704 pcm_config_low_latency.start_threshold = trial / 4;
10705 pcm_config_low_latency.avail_min = trial / 4;
10706 configured_low_latency_capture_period_size = trial;
10707 }
10708 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010709 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10710 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010711 trial = atoi(value);
10712 if (period_size_is_plausible_for_low_latency(trial)) {
10713 configured_low_latency_capture_period_size = trial;
10714 }
10715 }
10716
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010717 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10718
Eric Laurent4b084132018-10-19 17:33:43 -070010719 adev->camera_orientation = CAMERA_DEFAULT;
10720
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010721 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010722 af_period_multiplier = atoi(value);
10723 if (af_period_multiplier < 0)
10724 af_period_multiplier = 2;
10725 else if (af_period_multiplier > 4)
10726 af_period_multiplier = 4;
10727
10728 ALOGV("new period_multiplier = %d", af_period_multiplier);
10729 }
10730
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010731 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010732
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010733 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010734 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010735 pthread_mutex_unlock(&adev_init_lock);
10736
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010737 if (adev->adm_init)
10738 adev->adm_data = adev->adm_init();
10739
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010740 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010741 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010742
10743 audio_extn_snd_mon_init();
10744 pthread_mutex_lock(&adev->lock);
10745 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10746 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010747 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10748 /*
10749 * if the battery state callback happens before charging can be queried,
10750 * it will be guarded with the adev->lock held in the cb function and so
10751 * the callback value will reflect the latest state
10752 */
10753 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010754 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010755 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010756 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010757 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010758 /* Allocate memory for Device config params */
10759 adev->device_cfg_params = (struct audio_device_config_param*)
10760 calloc(platform_get_max_codec_backend(),
10761 sizeof(struct audio_device_config_param));
10762 if (adev->device_cfg_params == NULL)
10763 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010764
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010765 /*
10766 * Check if new PSPD matrix mixer control is supported. If not
10767 * supported, then set flag so that old mixer ctrl is sent while
10768 * sending pspd coefficients on older kernel version. Query mixer
10769 * control for default pcm id and channel value one.
10770 */
10771 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10772 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10773
10774 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10775 if (!ctl) {
10776 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10777 __func__, mixer_ctl_name);
10778 adev->use_old_pspd_mix_ctrl = true;
10779 }
10780
Eric Laurent994a6932013-07-17 11:51:42 -070010781 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010782 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010783
10784adev_open_err:
10785 free_map(adev->patch_map);
10786 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010787 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010788 pthread_mutex_destroy(&adev->lock);
10789 free(adev);
10790 adev = NULL;
10791 *device = NULL;
10792 pthread_mutex_unlock(&adev_init_lock);
10793 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010794}
10795
10796static struct hw_module_methods_t hal_module_methods = {
10797 .open = adev_open,
10798};
10799
10800struct audio_module HAL_MODULE_INFO_SYM = {
10801 .common = {
10802 .tag = HARDWARE_MODULE_TAG,
10803 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10804 .hal_api_version = HARDWARE_HAL_API_VERSION,
10805 .id = AUDIO_HARDWARE_MODULE_ID,
10806 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010807 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010808 .methods = &hal_module_methods,
10809 },
10810};