blob: 4516448a0ac94a75b139b8317444072e5bbd759f [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530402 /* For Interactive Audio Streams */
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700411
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800412 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
413
Derek Chenf6318be2017-06-12 17:16:24 -0400414 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
415
416 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
417 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
418 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
419 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800420 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700421 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530422 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700423};
424
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700425static const audio_usecase_t offload_usecases[] = {
426 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700435};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436
Varun Balaraje49253e2017-07-06 19:48:56 +0530437static const audio_usecase_t interactive_usecases[] = {
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
446};
447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448#define STRING_TO_ENUM(string) { #string, string }
449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450struct string_to_enum {
451 const char *name;
452 uint32_t value;
453};
454
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800475};
476
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700477static const struct string_to_enum formats_name_to_enum_table[] = {
478 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700481 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
482 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700484 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800485 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
486 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700487 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800488};
489
490//list of all supported sample rates by HDMI specification.
491static const int out_hdmi_sample_rates[] = {
492 32000, 44100, 48000, 88200, 96000, 176400, 192000,
493};
494
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700495static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800496 STRING_TO_ENUM(32000),
497 STRING_TO_ENUM(44100),
498 STRING_TO_ENUM(48000),
499 STRING_TO_ENUM(88200),
500 STRING_TO_ENUM(96000),
501 STRING_TO_ENUM(176400),
502 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800503 STRING_TO_ENUM(352800),
504 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700505};
506
Carter Hsu2e429db2019-05-14 18:50:52 +0800507struct in_effect_list {
508 struct listnode list;
509 effect_handle_t handle;
510};
511
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700512static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700513static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700514static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700515//cache last MBDRC cal step level
516static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700517
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700519static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800520static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530521static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530522
Derek Chen6f293672019-04-01 01:40:24 -0700523static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
524static void in_snd_mon_cb(void * stream, struct str_parms * parms);
525static void out_snd_mon_cb(void * stream, struct str_parms * parms);
526
Zhou Song331c8e52019-08-26 14:16:12 +0800527static int configure_btsco_sample_rate(snd_device_t snd_device);
528
Vatsal Buchac09ae062018-11-14 13:25:08 +0530529#ifdef AUDIO_FEATURE_ENABLED_GCOV
530extern void __gcov_flush();
531static void enable_gcov()
532{
533 __gcov_flush();
534}
535#else
536static void enable_gcov()
537{
538}
539#endif
540
justinweng20fb6d82019-02-21 18:49:00 -0700541static int in_set_microphone_direction(const struct audio_stream_in *stream,
542 audio_microphone_direction_t dir);
543static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
544
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700545static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
546 int flags __unused)
547{
548 int dir = 0;
549 switch (uc_id) {
550 case USECASE_AUDIO_RECORD_LOW_LATENCY:
551 dir = 1;
552 case USECASE_AUDIO_PLAYBACK_ULL:
553 break;
554 default:
555 return false;
556 }
557
558 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
559 PCM_PLAYBACK : PCM_CAPTURE);
560 if (adev->adm_is_noirq_avail)
561 return adev->adm_is_noirq_avail(adev->adm_data,
562 adev->snd_card, dev_id, dir);
563 return false;
564}
565
566static void register_out_stream(struct stream_out *out)
567{
568 struct audio_device *adev = out->dev;
569 if (is_offload_usecase(out->usecase) ||
570 !adev->adm_register_output_stream)
571 return;
572
573 // register stream first for backward compatibility
574 adev->adm_register_output_stream(adev->adm_data,
575 out->handle,
576 out->flags);
577
578 if (!adev->adm_set_config)
579 return;
580
581 if (out->realtime)
582 adev->adm_set_config(adev->adm_data,
583 out->handle,
584 out->pcm, &out->config);
585}
586
587static void register_in_stream(struct stream_in *in)
588{
589 struct audio_device *adev = in->dev;
590 if (!adev->adm_register_input_stream)
591 return;
592
593 adev->adm_register_input_stream(adev->adm_data,
594 in->capture_handle,
595 in->flags);
596
597 if (!adev->adm_set_config)
598 return;
599
600 if (in->realtime)
601 adev->adm_set_config(adev->adm_data,
602 in->capture_handle,
603 in->pcm,
604 &in->config);
605}
606
607static void request_out_focus(struct stream_out *out, long ns)
608{
609 struct audio_device *adev = out->dev;
610
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611 if (adev->adm_request_focus_v2)
612 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
613 else if (adev->adm_request_focus)
614 adev->adm_request_focus(adev->adm_data, out->handle);
615}
616
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700617static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618{
619 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700622 if (adev->adm_request_focus_v2_1)
623 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
624 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700625 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
626 else if (adev->adm_request_focus)
627 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700628
629 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700630}
631
632static void release_out_focus(struct stream_out *out)
633{
634 struct audio_device *adev = out->dev;
635
636 if (adev->adm_abandon_focus)
637 adev->adm_abandon_focus(adev->adm_data, out->handle);
638}
639
640static void release_in_focus(struct stream_in *in)
641{
642 struct audio_device *adev = in->dev;
643 if (adev->adm_abandon_focus)
644 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
645}
646
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530647static int parse_snd_card_status(struct str_parms *parms, int *card,
648 card_status_t *status)
649{
650 char value[32]={0};
651 char state[32]={0};
652
653 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
654 if (ret < 0)
655 return -1;
656
657 // sscanf should be okay as value is of max length 32.
658 // same as sizeof state.
659 if (sscanf(value, "%d,%s", card, state) < 2)
660 return -1;
661
662 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
663 CARD_STATUS_OFFLINE;
664 return 0;
665}
666
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700667static inline void adjust_frames_for_device_delay(struct stream_out *out,
668 uint32_t *dsp_frames) {
669 // Adjustment accounts for A2dp encoder latency with offload usecases
670 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800671 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700672 unsigned long offset =
673 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
674 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
675 }
676}
677
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700678static inline bool free_entry(void *key __unused,
679 void *value, void *context __unused)
680{
681 free(value);
682 return true;
683}
684
685static inline void free_map(Hashmap *map)
686{
687 if (map) {
688 hashmapForEach(map, free_entry, (void *) NULL);
689 hashmapFree(map);
690 }
691}
692
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800693static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700694 audio_patch_handle_t patch_handle)
695{
696 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
697 return;
698
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699 struct audio_patch_info *p_info =
700 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
701 if (p_info) {
702 ALOGV("%s: Remove patch %d", __func__, patch_handle);
703 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
704 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700705 free(p_info);
706 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700707}
708
709static inline int io_streams_map_insert(struct audio_device *adev,
710 struct audio_stream *stream,
711 audio_io_handle_t handle,
712 audio_patch_handle_t patch_handle)
713{
714 struct audio_stream_info *s_info =
715 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
716
717 if (s_info == NULL) {
718 ALOGE("%s: Could not allocate stream info", __func__);
719 return -ENOMEM;
720 }
721 s_info->stream = stream;
722 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723
724 pthread_mutex_lock(&adev->lock);
725 struct audio_stream_info *stream_info =
726 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700727 if (stream_info != NULL)
728 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800729 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700730 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
731 return 0;
732}
733
734static inline void io_streams_map_remove(struct audio_device *adev,
735 audio_io_handle_t handle)
736{
737 pthread_mutex_lock(&adev->lock);
738 struct audio_stream_info *s_info =
739 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700742 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800743 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700744 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800745done:
746 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 return;
748}
749
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800750static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700751 audio_patch_handle_t handle)
752{
753 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 p_info = (struct audio_patch_info *)
755 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700756 return p_info;
757}
758
vivek mehtaa76401a2015-04-24 14:12:15 -0700759__attribute__ ((visibility ("default")))
760bool audio_hw_send_gain_dep_calibration(int level) {
761 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700762 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700763
764 pthread_mutex_lock(&adev_init_lock);
765
766 if (adev != NULL && adev->platform != NULL) {
767 pthread_mutex_lock(&adev->lock);
768 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530770 // cache level info for any of the use case which
771 // was not started.
772 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700773
vivek mehtaa76401a2015-04-24 14:12:15 -0700774 pthread_mutex_unlock(&adev->lock);
775 } else {
776 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
777 }
778
779 pthread_mutex_unlock(&adev_init_lock);
780
781 return ret_val;
782}
783
Ashish Jain5106d362016-05-11 19:23:33 +0530784static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
785{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800786 bool gapless_enabled = false;
787 const char *mixer_ctl_name = "Compress Gapless Playback";
788 struct mixer_ctl *ctl;
789
790 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700791 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530792
793 /*Disable gapless if its AV playback*/
794 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800795
796 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
797 if (!ctl) {
798 ALOGE("%s: Could not get ctl for mixer cmd - %s",
799 __func__, mixer_ctl_name);
800 return -EINVAL;
801 }
802
803 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
804 ALOGE("%s: Could not set gapless mode %d",
805 __func__, gapless_enabled);
806 return -EINVAL;
807 }
808 return 0;
809}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700810
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700811__attribute__ ((visibility ("default")))
812int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
813 int table_size) {
814 int ret_val = 0;
815 ALOGV("%s: enter ... ", __func__);
816
817 pthread_mutex_lock(&adev_init_lock);
818 if (adev == NULL) {
819 ALOGW("%s: adev is NULL .... ", __func__);
820 goto done;
821 }
822
823 pthread_mutex_lock(&adev->lock);
824 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
825 pthread_mutex_unlock(&adev->lock);
826done:
827 pthread_mutex_unlock(&adev_init_lock);
828 ALOGV("%s: exit ... ", __func__);
829 return ret_val;
830}
831
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800832bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800833{
834 bool ret = false;
835 ALOGV("%s: enter ...", __func__);
836
837 pthread_mutex_lock(&adev_init_lock);
838
839 if (adev != NULL && adev->platform != NULL) {
840 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800841 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800842 pthread_mutex_unlock(&adev->lock);
843 }
844
845 pthread_mutex_unlock(&adev_init_lock);
846
847 ALOGV("%s: exit with ret %d", __func__, ret);
848 return ret;
849}
Aalique Grahame22e49102018-12-18 14:23:57 -0800850
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700851static bool is_supported_format(audio_format_t format)
852{
Eric Laurent86e17132013-09-12 17:49:30 -0700853 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530854 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530855 format == AUDIO_FORMAT_AAC_LC ||
856 format == AUDIO_FORMAT_AAC_HE_V1 ||
857 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530858 format == AUDIO_FORMAT_AAC_ADTS_LC ||
859 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530861 format == AUDIO_FORMAT_AAC_LATM_LC ||
862 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530864 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
865 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530866 format == AUDIO_FORMAT_PCM_FLOAT ||
867 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700868 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530869 format == AUDIO_FORMAT_AC3 ||
870 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700871 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530872 format == AUDIO_FORMAT_DTS ||
873 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800874 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530875 format == AUDIO_FORMAT_ALAC ||
876 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530877 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530878 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800879 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530880 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700881 format == AUDIO_FORMAT_APTX ||
882 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800883 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700884
885 return false;
886}
887
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888static inline bool is_mmap_usecase(audio_usecase_t uc_id)
889{
890 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800891 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700892 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
893}
894
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700895static inline bool is_valid_volume(float left, float right)
896{
897 return ((left >= 0.0f && right >= 0.0f) ? true : false);
898}
899
Avinash Vaish71a8b972014-07-24 15:36:33 +0530900static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
901 struct audio_usecase *uc_info)
902{
903 struct listnode *node;
904 struct audio_usecase *usecase;
905
906 if (uc_info == NULL)
907 return -EINVAL;
908
909 /* Re-route all voice usecases on the shared backend other than the
910 specified usecase to new snd devices */
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800913 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530914 enable_audio_route(adev, usecase);
915 }
916 return 0;
917}
918
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530919static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530920{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530921 ALOGV("%s", __func__);
922 audio_route_apply_and_update_path(adev->audio_route,
923 "asrc-mode");
924 adev->asrc_mode_enabled = true;
925}
926
927static void disable_asrc_mode(struct audio_device *adev)
928{
929 ALOGV("%s", __func__);
930 audio_route_reset_and_update_path(adev->audio_route,
931 "asrc-mode");
932 adev->asrc_mode_enabled = false;
933}
934
935/*
936 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
937 * 44.1 or Native DSD backends are enabled for any of current use case.
938 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
939 * - Disable current mix path use case(Headphone backend) and re-enable it with
940 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
941 * e.g. Naitve DSD or Headphone 44.1 -> + 48
942 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530943static void check_and_set_asrc_mode(struct audio_device *adev,
944 struct audio_usecase *uc_info,
945 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530946{
947 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530948 int i, num_new_devices = 0;
949 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
950 /*
951 *Split snd device for new combo use case
952 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
953 */
954 if (platform_split_snd_device(adev->platform,
955 snd_device,
956 &num_new_devices,
957 split_new_snd_devices) == 0) {
958 for (i = 0; i < num_new_devices; i++)
959 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
960 } else {
961 int new_backend_idx = platform_get_backend_index(snd_device);
962 if (((new_backend_idx == HEADPHONE_BACKEND) ||
963 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
964 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
965 !adev->asrc_mode_enabled) {
966 struct listnode *node = NULL;
967 struct audio_usecase *uc = NULL;
968 struct stream_out *curr_out = NULL;
969 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
970 int i, num_devices, ret = 0;
971 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530972
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530973 list_for_each(node, &adev->usecase_list) {
974 uc = node_to_item(node, struct audio_usecase, list);
975 curr_out = (struct stream_out*) uc->stream.out;
976 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
977 /*
978 *Split snd device for existing combo use case
979 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
980 */
981 ret = platform_split_snd_device(adev->platform,
982 uc->out_snd_device,
983 &num_devices,
984 split_snd_devices);
985 if (ret < 0 || num_devices == 0) {
986 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
987 split_snd_devices[0] = uc->out_snd_device;
988 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800989 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530990 for (i = 0; i < num_devices; i++) {
991 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
992 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
993 if((new_backend_idx == HEADPHONE_BACKEND) &&
994 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
995 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
996 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
997 __func__);
998 enable_asrc_mode(adev);
999 break;
1000 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1001 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1002 (usecase_backend_idx == HEADPHONE_BACKEND)) {
1003 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1004 __func__);
1005 disable_audio_route(adev, uc);
1006 disable_snd_device(adev, uc->out_snd_device);
1007 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1008 if (new_backend_idx == DSD_NATIVE_BACKEND)
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-true-highquality-mode");
1011 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1012 (curr_out->bit_width >= 24))
1013 audio_route_apply_and_update_path(adev->audio_route,
1014 "hph-highquality-mode");
1015 enable_asrc_mode(adev);
1016 enable_snd_device(adev, uc->out_snd_device);
1017 enable_audio_route(adev, uc);
1018 break;
1019 }
1020 }
1021 // reset split devices count
1022 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001023 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301024 if (adev->asrc_mode_enabled)
1025 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301026 }
1027 }
1028 }
1029}
1030
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1032 struct audio_effect_config effect_config,
1033 unsigned int param_value)
1034{
1035 char mixer_ctl_name[] = "Audio Effect";
1036 struct mixer_ctl *ctl;
1037 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001038 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001039
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001040 if (in == NULL) {
1041 ALOGE("%s: active input stream is NULL", __func__);
1042 return -EINVAL;
1043 }
1044
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001045 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1046 if (!ctl) {
1047 ALOGE("%s: Could not get mixer ctl - %s",
1048 __func__, mixer_ctl_name);
1049 return -EINVAL;
1050 }
1051
1052 set_values[0] = 1; //0:Rx 1:Tx
1053 set_values[1] = in->app_type_cfg.app_type;
1054 set_values[2] = (long)effect_config.module_id;
1055 set_values[3] = (long)effect_config.instance_id;
1056 set_values[4] = (long)effect_config.param_id;
1057 set_values[5] = param_value;
1058
1059 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1060
1061 return 0;
1062
1063}
1064
1065static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1066 int effect_type, unsigned int *param_value)
1067{
1068 int ret = 0;
1069 struct audio_effect_config other_effect_config;
1070 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001071 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001072
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001073 if (in == NULL) {
1074 ALOGE("%s: active input stream is NULL", __func__);
1075 return -EINVAL;
1076 }
1077
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001078 usecase = get_usecase_from_list(adev, in->usecase);
1079 if (!usecase)
1080 return -EINVAL;
1081
1082 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1083 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1084 if (ret < 0) {
1085 ALOGE("%s Failed to get effect params %d", __func__, ret);
1086 return ret;
1087 }
1088
1089 if (module_id == other_effect_config.module_id) {
1090 //Same module id for AEC/NS. Values need to be combined
1091 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1092 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1093 *param_value |= other_effect_config.param_value;
1094 }
1095 }
1096
1097 return ret;
1098}
1099
1100static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301101{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 struct audio_effect_config effect_config;
1103 struct audio_usecase *usecase = NULL;
1104 int ret = 0;
1105 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001106 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001108 if(!voice_extn_is_dynamic_ecns_enabled())
1109 return ENOSYS;
1110
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001111 if (!in) {
1112 ALOGE("%s: Invalid input stream", __func__);
1113 return -EINVAL;
1114 }
1115
1116 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1117
1118 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001119 if (usecase == NULL) {
1120 ALOGE("%s: Could not find the usecase (%d) in the list",
1121 __func__, in->usecase);
1122 return -EINVAL;
1123 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001124
1125 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1126 if (ret < 0) {
1127 ALOGE("%s Failed to get module id %d", __func__, ret);
1128 return ret;
1129 }
1130 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1131 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1132
1133 if(enable)
1134 param_value = effect_config.param_value;
1135
1136 /*Special handling for AEC & NS effects Param values need to be
1137 updated if module ids are same*/
1138
1139 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1140 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1141 if (ret < 0)
1142 return ret;
1143 }
1144
1145 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1146
1147 return ret;
1148}
1149
1150static void check_and_enable_effect(struct audio_device *adev)
1151{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001152 if(!voice_extn_is_dynamic_ecns_enabled())
1153 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001154
Eric Laurent637e2d42018-11-15 12:24:31 -08001155 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156
Eric Laurent637e2d42018-11-15 12:24:31 -08001157 if (in != NULL && !in->standby) {
1158 if (in->enable_aec)
1159 enable_disable_effect(adev, EFFECT_AEC, true);
1160
1161 if (in->enable_ns &&
1162 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1163 enable_disable_effect(adev, EFFECT_NS, true);
1164 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001165 }
1166}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001167
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001168int pcm_ioctl(struct pcm *pcm, int request, ...)
1169{
1170 va_list ap;
1171 void * arg;
1172 int pcm_fd = *(int*)pcm;
1173
1174 va_start(ap, request);
1175 arg = va_arg(ap, void *);
1176 va_end(ap);
1177
1178 return ioctl(pcm_fd, request, arg);
1179}
1180
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001181int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001182 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001185 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301186 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301187 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001188 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301189 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001190
1191 if (usecase == NULL)
1192 return -EINVAL;
1193
1194 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1195
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 if (usecase->type == PCM_CAPTURE) {
1197 struct stream_in *in = usecase->stream.in;
1198 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001200
1201 if (in) {
1202 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001203 list_init(&out_devices);
1204 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001205 struct listnode *node;
1206 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1207 USECASE_AUDIO_PLAYBACK_VOIP);
1208 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else if (adev->primary_output &&
1212 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001213 assign_devices(&out_devices,
1214 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001215 } else {
1216 list_for_each(node, &adev->usecase_list) {
1217 uinfo = node_to_item(node, struct audio_usecase, list);
1218 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001219 assign_devices(&out_devices,
1220 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001221 break;
1222 }
1223 }
1224 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001225
1226 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 in->ec_opened = true;
1228 }
1229 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001230 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1231 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1232 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001233 snd_device = usecase->in_snd_device;
1234 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001235 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001236 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001237
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001238#ifdef DS1_DOLBY_DAP_ENABLED
1239 audio_extn_dolby_set_dmid(adev);
1240 audio_extn_dolby_set_endpoint(adev);
1241#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001242 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001243 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301244 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001245 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001246 if (audio_extn_is_maxx_audio_enabled())
1247 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301248 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301249 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1250 out = usecase->stream.out;
1251 if (out && out->compr)
1252 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1253 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254
1255 if (usecase->type == PCM_CAPTURE) {
1256 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001257 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301258 ALOGD("%s: set custom mtmx params v1", __func__);
1259 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1260 }
1261 } else {
1262 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1263 }
Manish Dewangan58229382017-02-02 15:48:41 +05301264
Andy Hung756ecc12018-10-19 17:47:12 -07001265 // we shouldn't truncate mixer_path
1266 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1267 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1268 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001269 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001270 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301271 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1272 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1273 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1274 if (parms) {
1275 audio_extn_fm_set_parameters(adev, parms);
1276 str_parms_destroy(parms);
1277 }
1278 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 ALOGV("%s: exit", __func__);
1280 return 0;
1281}
1282
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001284 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001287 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301288 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001289
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301290 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001291 return -EINVAL;
1292
1293 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301294 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 snd_device = usecase->in_snd_device;
1296 else
1297 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001298
1299 /* disable island and power mode on supported device for voice call */
1300 if (usecase->type == VOICE_CALL) {
1301 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1302 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1303 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1304 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1305 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1306 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1307 ALOGD("%s: disable island cfg and power mode in voice tx path",
1308 __func__);
1309 }
1310 }
1311 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1312 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1313 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1314 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1315 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1316 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1317 ALOGD("%s: disable island cfg and power mode in voice rx path",
1318 __func__);
1319 }
1320 }
1321 }
1322
Andy Hung756ecc12018-10-19 17:47:12 -07001323 // we shouldn't truncate mixer_path
1324 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1325 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1326 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001327 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001328 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001329 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001330 if (usecase->type == PCM_CAPTURE) {
1331 struct stream_in *in = usecase->stream.in;
1332 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001333 struct listnode out_devices;
1334 list_init(&out_devices);
1335 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001336 in->ec_opened = false;
1337 }
1338 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001339 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301340 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341
1342 if (usecase->type == PCM_CAPTURE) {
1343 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001344 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301345 ALOGD("%s: reset custom mtmx params v1", __func__);
1346 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1347 }
1348 } else {
1349 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1350 }
1351
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001352 if ((usecase->type == PCM_PLAYBACK) &&
1353 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301354 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 ALOGV("%s: exit", __func__);
1357 return 0;
1358}
1359
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001360int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001361 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001362{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301363 int i, num_devices = 0;
1364 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001365 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1366
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001367 if (snd_device < SND_DEVICE_MIN ||
1368 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001369 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001370 return -EINVAL;
1371 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001374 ALOGE("%s: Invalid sound device returned", __func__);
1375 return -EINVAL;
1376 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001377
1378 adev->snd_dev_ref_cnt[snd_device]++;
1379
1380 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1381 (platform_split_snd_device(adev->platform,
1382 snd_device,
1383 &num_devices,
1384 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001385 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001386 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001387 /* Set backend config for A2DP to ensure slimbus configuration
1388 is correct if A2DP is already active and backend is closed
1389 and re-opened */
1390 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1391 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 return 0;
1393 }
1394
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001395 if (audio_extn_spkr_prot_is_enabled())
1396 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001397
Aalique Grahame22e49102018-12-18 14:23:57 -08001398 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1399
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001400 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1401 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001402 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1403 goto err;
1404 }
1405 audio_extn_dev_arbi_acquire(snd_device);
1406 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001407 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001408 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001409 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001410 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001411 } else if (platform_split_snd_device(adev->platform,
1412 snd_device,
1413 &num_devices,
1414 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301415 for (i = 0; i < num_devices; i++) {
1416 enable_snd_device(adev, new_snd_devices[i]);
1417 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001418 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001419 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001420 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301421
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001422 /* enable island and power mode on supported device */
1423 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1424 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1425 platform_set_island_cfg_on_device(adev, snd_device, true);
1426 platform_set_power_mode_on_device(adev, snd_device, true);
1427 ALOGD("%s: enable island cfg and power mode on: %s",
1428 __func__, device_name);
1429 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301430
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301431 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1432 if (audio_extn_a2dp_start_playback() < 0) {
1433 ALOGE(" fail to configure A2dp Source control path ");
1434 goto err;
1435 } else {
1436 adev->a2dp_started = true;
1437 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001438 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001439
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001440 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1441 (audio_extn_a2dp_start_capture() < 0)) {
1442 ALOGE(" fail to configure A2dp Sink control path ");
1443 goto err;
1444 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301445
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001446 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1447 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1448 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1449 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1450 ALOGE(" fail to configure sco control path ");
1451 goto err;
1452 }
Zhou Song12c29502019-03-16 10:37:18 +08001453 }
1454
Zhou Song331c8e52019-08-26 14:16:12 +08001455 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001456 /* due to the possibility of calibration overwrite between listen
1457 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001458 audio_extn_sound_trigger_update_device_status(snd_device,
1459 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301460 audio_extn_listen_update_device_status(snd_device,
1461 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001462 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001463 audio_extn_sound_trigger_update_device_status(snd_device,
1464 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301465 audio_extn_listen_update_device_status(snd_device,
1466 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001467 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001468 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001469 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001470 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301471
1472 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1473 !adev->native_playback_enabled &&
1474 audio_is_true_native_stream_active(adev)) {
1475 ALOGD("%s: %d: napb: enabling native mode in hardware",
1476 __func__, __LINE__);
1477 audio_route_apply_and_update_path(adev->audio_route,
1478 "true-native-mode");
1479 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301480 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301481 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1482 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001483 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001484 ALOGD("%s: init ec ref loopback", __func__);
1485 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1486 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001489err:
1490 adev->snd_dev_ref_cnt[snd_device]--;
1491 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492}
1493
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001494int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001495 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301497 int i, num_devices = 0;
1498 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001499 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1500
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001501 if (snd_device < SND_DEVICE_MIN ||
1502 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001503 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001504 return -EINVAL;
1505 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001506
1507 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1508 ALOGE("%s: Invalid sound device returned", __func__);
1509 return -EINVAL;
1510 }
1511
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001512 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1513 ALOGE("%s: device ref cnt is already 0", __func__);
1514 return -EINVAL;
1515 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001516
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001518
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001519
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001521 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301522
Aalique Grahame22e49102018-12-18 14:23:57 -08001523 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1524
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001525 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1526 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001527 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001528
1529 // when speaker device is disabled, reset swap.
1530 // will be renabled on usecase start
1531 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001532 } else if (platform_split_snd_device(adev->platform,
1533 snd_device,
1534 &num_devices,
1535 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301536 for (i = 0; i < num_devices; i++) {
1537 disable_snd_device(adev, new_snd_devices[i]);
1538 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001539 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001540 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001541 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001542 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001543
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301544 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301545 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301546 adev->a2dp_started = false;
1547 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001548 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001549 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001550 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301551 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001552 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301553 adev->native_playback_enabled) {
1554 ALOGD("%s: %d: napb: disabling native mode in hardware",
1555 __func__, __LINE__);
1556 audio_route_reset_and_update_path(adev->audio_route,
1557 "true-native-mode");
1558 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001559 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301560 adev->asrc_mode_enabled) {
1561 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301562 disable_asrc_mode(adev);
1563 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001564 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301565 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001566 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001567 ALOGD("%s: deinit ec ref loopback", __func__);
1568 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1569 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001570
1571 audio_extn_utils_release_snd_device(snd_device);
1572 } else {
1573 if (platform_split_snd_device(adev->platform,
1574 snd_device,
1575 &num_devices,
1576 new_snd_devices) == 0) {
1577 for (i = 0; i < num_devices; i++) {
1578 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1579 }
1580 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001581 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 return 0;
1584}
1585
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001586/*
1587 legend:
1588 uc - existing usecase
1589 new_uc - new usecase
1590 d1, d11, d2 - SND_DEVICE enums
1591 a1, a2 - corresponding ANDROID device enums
1592 B1, B2 - backend strings
1593
1594case 1
1595 uc->dev d1 (a1) B1
1596 new_uc->dev d1 (a1), d2 (a2) B1, B2
1597
1598 resolution: disable and enable uc->dev on d1
1599
1600case 2
1601 uc->dev d1 (a1) B1
1602 new_uc->dev d11 (a1) B1
1603
1604 resolution: need to switch uc since d1 and d11 are related
1605 (e.g. speaker and voice-speaker)
1606 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1607
1608case 3
1609 uc->dev d1 (a1) B1
1610 new_uc->dev d2 (a2) B2
1611
1612 resolution: no need to switch uc
1613
1614case 4
1615 uc->dev d1 (a1) B1
1616 new_uc->dev d2 (a2) B1
1617
1618 resolution: disable enable uc-dev on d2 since backends match
1619 we cannot enable two streams on two different devices if they
1620 share the same backend. e.g. if offload is on speaker device using
1621 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1622 using the same backend, offload must also be switched to voice-handset.
1623
1624case 5
1625 uc->dev d1 (a1) B1
1626 new_uc->dev d1 (a1), d2 (a2) B1
1627
1628 resolution: disable enable uc-dev on d2 since backends match
1629 we cannot enable two streams on two different devices if they
1630 share the same backend.
1631
1632case 6
1633 uc->dev d1 (a1) B1
1634 new_uc->dev d2 (a1) B2
1635
1636 resolution: no need to switch
1637
1638case 7
1639 uc->dev d1 (a1), d2 (a2) B1, B2
1640 new_uc->dev d1 (a1) B1
1641
1642 resolution: no need to switch
1643
Zhou Song4ba65882018-07-09 14:48:07 +08001644case 8
1645 uc->dev d1 (a1) B1
1646 new_uc->dev d11 (a1), d2 (a2) B1, B2
1647 resolution: compared to case 1, for this case, d1 and d11 are related
1648 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301649
1650case 9
1651 uc->dev d1 (a1), d2(a2) B1 B2
1652 new_uc->dev d1 (a1), d22 (a2) B1, B2
1653 resolution: disable enable uc-dev on d2 since backends match
1654 we cannot enable two streams on two different devices if they
1655 share the same backend. This is special case for combo use case
1656 with a2dp and sco devices which uses same backend.
1657 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001658*/
1659static snd_device_t derive_playback_snd_device(void * platform,
1660 struct audio_usecase *uc,
1661 struct audio_usecase *new_uc,
1662 snd_device_t new_snd_device)
1663{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001664 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001665
1666 snd_device_t d1 = uc->out_snd_device;
1667 snd_device_t d2 = new_snd_device;
1668
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001669 list_init(&a1);
1670 list_init(&a2);
1671
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301672 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301673 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001674 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1675 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301676 break;
1677 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 assign_devices(&a1, &uc->stream.out->device_list);
1679 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301680 break;
1681 }
1682
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001683 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001684 if (!compare_devices(&a1, &a2) &&
1685 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001686 snd_device_t d3[2];
1687 int num_devices = 0;
1688 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001689 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001690 &num_devices,
1691 d3);
1692 if (ret < 0) {
1693 if (ret != -ENOSYS) {
1694 ALOGW("%s failed to split snd_device %d",
1695 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001696 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001697 }
1698 goto end;
1699 }
1700
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701 if (platform_check_backends_match(d3[0], d3[1])) {
1702 return d2; // case 5
1703 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301704 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1705 platform_check_backends_match(d1, d2))
1706 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001707 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301708 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001709 // check if d1 is related to any of d3's
1710 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001711 return d1; // case 1
1712 else
1713 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001714 }
1715 } else {
1716 if (platform_check_backends_match(d1, d2)) {
1717 return d2; // case 2, 4
1718 } else {
1719 return d1; // case 6, 3
1720 }
1721 }
1722
1723end:
1724 return d2; // return whatever was calculated before.
1725}
1726
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301728 struct audio_usecase *uc_info,
1729 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001730{
1731 struct listnode *node;
1732 struct audio_usecase *usecase;
1733 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301734 snd_device_t uc_derive_snd_device;
1735 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001736 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1737 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001738 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301739 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001740 /*
1741 * This function is to make sure that all the usecases that are active on
1742 * the hardware codec backend are always routed to any one device that is
1743 * handled by the hardware codec.
1744 * For example, if low-latency and deep-buffer usecases are currently active
1745 * on speaker and out_set_parameters(headset) is received on low-latency
1746 * output, then we have to make sure deep-buffer is also switched to headset,
1747 * because of the limitation that both the devices cannot be enabled
1748 * at the same time as they share the same backend.
1749 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001750 /*
1751 * This call is to check if we need to force routing for a particular stream
1752 * If there is a backend configuration change for the device when a
1753 * new stream starts, then ADM needs to be closed and re-opened with the new
1754 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001755 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001756 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001757 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1758 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301759 /* For a2dp device reconfigure all active sessions
1760 * with new AFE encoder format based on a2dp state
1761 */
1762 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301763 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1764 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301765 audio_extn_a2dp_is_force_device_switch()) {
1766 force_routing = true;
1767 force_restart_session = true;
1768 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001769
1770 /*
1771 * Island cfg and power mode config needs to set before AFE port start.
1772 * Set force routing in case of voice device was enable before.
1773 */
1774 if (uc_info->type == VOICE_CALL &&
1775 voice_extn_is_voice_power_mode_supported() &&
1776 platform_check_and_update_island_power_status(adev->platform,
1777 uc_info,
1778 snd_device)) {
1779 force_routing = true;
1780 ALOGD("%s:becf: force routing %d for power mode supported device",
1781 __func__, force_routing);
1782 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301783 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1784
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001786 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001787 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001788 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1789 switch_device[i] = false;
1790
1791 list_for_each(node, &adev->usecase_list) {
1792 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001793
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301794 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1795 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301796 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301797 platform_get_snd_device_name(usecase->out_snd_device),
1798 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301799 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1800 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301801 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1802 usecase, uc_info, snd_device);
1803 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001804 (is_codec_backend_out_device_type(&usecase->device_list) ||
1805 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1806 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1807 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1808 is_a2dp_out_device_type(&usecase->device_list) ||
1809 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301810 ((force_restart_session) ||
1811 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301812 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1813 __func__, use_case_table[usecase->id],
1814 platform_get_snd_device_name(usecase->out_snd_device));
1815 disable_audio_route(adev, usecase);
1816 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301817 /* Enable existing usecase on derived playback device */
1818 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301819 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301820 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821 }
1822 }
1823
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301824 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1825 num_uc_to_switch);
1826
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001828 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301830 /* Make sure the previous devices to be disabled first and then enable the
1831 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832 list_for_each(node, &adev->usecase_list) {
1833 usecase = node_to_item(node, struct audio_usecase, list);
1834 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001835 /* Check if output sound device to be switched can be split and if any
1836 of the split devices match with derived sound device */
1837 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1838 &num_devices, split_snd_devices) == 0) {
1839 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1840 for (i = 0; i < num_devices; i++) {
1841 /* Disable devices that do not match with derived sound device */
1842 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1843 disable_snd_device(adev, split_snd_devices[i]);
1844 }
1845 } else {
1846 disable_snd_device(adev, usecase->out_snd_device);
1847 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 }
1849 }
1850
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001851 list_for_each(node, &adev->usecase_list) {
1852 usecase = node_to_item(node, struct audio_usecase, list);
1853 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001854 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1855 &num_devices, split_snd_devices) == 0) {
1856 /* Enable derived sound device only if it does not match with
1857 one of the split sound devices. This is because the matching
1858 sound device was not disabled */
1859 bool should_enable = true;
1860 for (i = 0; i < num_devices; i++) {
1861 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1862 should_enable = false;
1863 break;
1864 }
1865 }
1866 if (should_enable)
1867 enable_snd_device(adev, derive_snd_device[usecase->id]);
1868 } else {
1869 enable_snd_device(adev, derive_snd_device[usecase->id]);
1870 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001871 }
1872 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 /* Re-route all the usecases on the shared backend other than the
1875 specified usecase to new snd devices */
1876 list_for_each(node, &adev->usecase_list) {
1877 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301878 /* Update the out_snd_device only before enabling the audio route */
1879 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301880 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301881 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301882 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301883 use_case_table[usecase->id],
1884 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001885 /* Update voc calibration before enabling VoIP route */
1886 if (usecase->type == VOIP_CALL)
1887 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001888 usecase->out_snd_device,
1889 platform_get_input_snd_device(
1890 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301891 &uc_info->device_list,
1892 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301893 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301894 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001895 out_set_voip_volume(&usecase->stream.out->stream,
1896 usecase->stream.out->volume_l,
1897 usecase->stream.out->volume_r);
1898 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 }
1901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902 }
1903}
1904
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301905static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001906 struct audio_usecase *uc_info,
1907 snd_device_t snd_device)
1908{
1909 struct listnode *node;
1910 struct audio_usecase *usecase;
1911 bool switch_device[AUDIO_USECASE_MAX];
1912 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001913 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001914 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001915
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301916 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1917 snd_device);
1918 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301919
1920 /*
1921 * Make sure out devices is checked against out codec backend device and
1922 * also in devices against in codec backend. Checking out device against in
1923 * codec backend or vice versa causes issues.
1924 */
1925 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001926 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001927
1928 /*
1929 * Island cfg and power mode config needs to set before AFE port start.
1930 * Set force routing in case of voice device was enable before.
1931 */
1932
1933 if (uc_info->type == VOICE_CALL &&
1934 voice_extn_is_voice_power_mode_supported() &&
1935 platform_check_and_update_island_power_status(adev->platform,
1936 uc_info,
1937 snd_device)) {
1938 force_routing = true;
1939 ALOGD("%s:becf: force routing %d for power mode supported device",
1940 __func__, force_routing);
1941 }
1942
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001943 /*
1944 * This function is to make sure that all the active capture usecases
1945 * are always routed to the same input sound device.
1946 * For example, if audio-record and voice-call usecases are currently
1947 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1948 * is received for voice call then we have to make sure that audio-record
1949 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1950 * because of the limitation that two devices cannot be enabled
1951 * at the same time if they share the same backend.
1952 */
1953 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1954 switch_device[i] = false;
1955
1956 list_for_each(node, &adev->usecase_list) {
1957 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301958 /*
1959 * TODO: Enhance below condition to handle BT sco/USB multi recording
1960 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301961
1962 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1963 (usecase->in_snd_device != snd_device || force_routing));
1964 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1965 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1966 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001967 ((backend_check_cond &&
1968 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001969 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001970 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001971 is_single_device_type_equal(&usecase->device_list,
1972 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001973 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001974 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001975 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301976 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001977 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001978 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001979 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001980 switch_device[usecase->id] = true;
1981 num_uc_to_switch++;
1982 }
1983 }
1984
1985 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001986 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001987
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301988 /* Make sure the previous devices to be disabled first and then enable the
1989 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001990 list_for_each(node, &adev->usecase_list) {
1991 usecase = node_to_item(node, struct audio_usecase, list);
1992 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001993 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001994 }
1995 }
1996
1997 list_for_each(node, &adev->usecase_list) {
1998 usecase = node_to_item(node, struct audio_usecase, list);
1999 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002000 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002001 }
2002 }
2003
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002004 /* Re-route all the usecases on the shared backend other than the
2005 specified usecase to new snd devices */
2006 list_for_each(node, &adev->usecase_list) {
2007 usecase = node_to_item(node, struct audio_usecase, list);
2008 /* Update the in_snd_device only before enabling the audio route */
2009 if (switch_device[usecase->id] ) {
2010 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002011 if (usecase->type != VOICE_CALL) {
2012 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302013 if (usecase->type == VOIP_CALL) {
2014 snd_device_t voip_snd_device;
2015 voip_snd_device = platform_get_output_snd_device(adev->platform,
2016 uc_info->stream.out,
2017 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002018 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302019 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002020 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302021 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302022 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002023 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002024 }
2025 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002026 }
2027}
2028
Mingming Yin3a941d42016-02-17 18:08:05 -08002029static void reset_hdmi_sink_caps(struct stream_out *out) {
2030 int i = 0;
2031
2032 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2033 out->supported_channel_masks[i] = 0;
2034 }
2035 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2036 out->supported_formats[i] = 0;
2037 }
2038 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2039 out->supported_sample_rates[i] = 0;
2040 }
2041}
2042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002044static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045{
Mingming Yin3a941d42016-02-17 18:08:05 -08002046 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002047 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2048 out->extconn.cs.controller,
2049 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Mingming Yin3a941d42016-02-17 18:08:05 -08002051 reset_hdmi_sink_caps(out);
2052
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002053 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002054 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002055 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002056 out->extconn.cs.stream);
2057 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002058 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002059 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002060 }
2061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002064 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002065 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002066 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2067 case 6:
2068 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2069 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2070 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2071 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2072 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2073 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 break;
2075 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002076 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002077 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 break;
2079 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002080
2081 // check channel format caps
2082 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002083 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2084 out->extconn.cs.controller,
2085 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002086 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2087 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2088 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2089 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2090 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2091 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2092 }
2093
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002094 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2095 out->extconn.cs.controller,
2096 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002097 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2098 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2099 }
2100
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002101 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2102 out->extconn.cs.controller,
2103 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002104 ALOGV(":%s HDMI supports DTS format", __func__);
2105 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2106 }
2107
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002108 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2109 out->extconn.cs.controller,
2110 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002111 ALOGV(":%s HDMI supports DTS HD format", __func__);
2112 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2113 }
2114
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002115 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2116 out->extconn.cs.controller,
2117 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002118 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2119 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2120 }
2121
Mingming Yin3a941d42016-02-17 18:08:05 -08002122
2123 // check sample rate caps
2124 i = 0;
2125 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002126 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2127 out->extconn.cs.controller,
2128 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002129 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2130 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2131 }
2132 }
2133
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002134 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135}
2136
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002137static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2138 uint32_t *supported_sample_rates __unused,
2139 uint32_t max_rates __unused)
2140{
2141 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2142 supported_sample_rates,
2143 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302144 ssize_t i = 0;
2145
2146 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002147 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2148 supported_sample_rates[i]);
2149 }
2150 return count;
2151}
2152
2153static inline int read_usb_sup_channel_masks(bool is_playback,
2154 audio_channel_mask_t *supported_channel_masks,
2155 uint32_t max_masks)
2156{
2157 int channels = audio_extn_usb_get_max_channels(is_playback);
2158 int channel_count;
2159 uint32_t num_masks = 0;
2160 if (channels > MAX_HIFI_CHANNEL_COUNT)
2161 channels = MAX_HIFI_CHANNEL_COUNT;
2162
2163 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002164 // start from 2 channels as framework currently doesn't support mono.
2165 if (channels >= FCC_2) {
2166 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2167 }
2168 for (channel_count = FCC_2;
2169 channel_count <= channels && num_masks < max_masks;
2170 ++channel_count) {
2171 supported_channel_masks[num_masks++] =
2172 audio_channel_mask_for_index_assignment_from_count(channel_count);
2173 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002174 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002175 // For capture we report all supported channel masks from 1 channel up.
2176 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002177 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2178 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002179 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2180 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2181 if (channel_count <= FCC_2) {
2182 mask = audio_channel_in_mask_from_count(channel_count);
2183 supported_channel_masks[num_masks++] = mask;
2184 }
2185 const audio_channel_mask_t index_mask =
2186 audio_channel_mask_for_index_assignment_from_count(channel_count);
2187 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2188 supported_channel_masks[num_masks++] = index_mask;
2189 }
2190 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002191 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302192
vincenttewf51c94e2019-05-07 10:28:53 +08002193 for (size_t i = 0; i < num_masks; ++i) {
2194 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2195 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302196 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002197 return num_masks;
2198}
2199
2200static inline int read_usb_sup_formats(bool is_playback __unused,
2201 audio_format_t *supported_formats,
2202 uint32_t max_formats __unused)
2203{
2204 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2205 switch (bitwidth) {
2206 case 24:
2207 // XXX : usb.c returns 24 for s24 and s24_le?
2208 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2209 break;
2210 case 32:
2211 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2212 break;
2213 case 16:
2214 default :
2215 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2216 break;
2217 }
2218 ALOGV("%s: %s supported format %d", __func__,
2219 is_playback ? "P" : "C", bitwidth);
2220 return 1;
2221}
2222
2223static inline int read_usb_sup_params_and_compare(bool is_playback,
2224 audio_format_t *format,
2225 audio_format_t *supported_formats,
2226 uint32_t max_formats,
2227 audio_channel_mask_t *mask,
2228 audio_channel_mask_t *supported_channel_masks,
2229 uint32_t max_masks,
2230 uint32_t *rate,
2231 uint32_t *supported_sample_rates,
2232 uint32_t max_rates) {
2233 int ret = 0;
2234 int num_formats;
2235 int num_masks;
2236 int num_rates;
2237 int i;
2238
2239 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2240 max_formats);
2241 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2242 max_masks);
2243
2244 num_rates = read_usb_sup_sample_rates(is_playback,
2245 supported_sample_rates, max_rates);
2246
2247#define LUT(table, len, what, dflt) \
2248 for (i=0; i<len && (table[i] != what); i++); \
2249 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2250
2251 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2252 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2253 LUT(supported_sample_rates, num_rates, *rate, 0);
2254
2255#undef LUT
2256 return ret < 0 ? -EINVAL : 0; // HACK TBD
2257}
2258
Alexy Josephb1379942016-01-29 15:49:38 -08002259audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002260 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002261{
2262 struct audio_usecase *usecase;
2263 struct listnode *node;
2264
2265 list_for_each(node, &adev->usecase_list) {
2266 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002267 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002268 ALOGV("%s: usecase id %d", __func__, usecase->id);
2269 return usecase->id;
2270 }
2271 }
2272 return USECASE_INVALID;
2273}
2274
Alexy Josephb1379942016-01-29 15:49:38 -08002275struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002276 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277{
2278 struct audio_usecase *usecase;
2279 struct listnode *node;
2280
2281 list_for_each(node, &adev->usecase_list) {
2282 usecase = node_to_item(node, struct audio_usecase, list);
2283 if (usecase->id == uc_id)
2284 return usecase;
2285 }
2286 return NULL;
2287}
2288
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302289/*
2290 * is a true native playback active
2291 */
2292bool audio_is_true_native_stream_active(struct audio_device *adev)
2293{
2294 bool active = false;
2295 int i = 0;
2296 struct listnode *node;
2297
2298 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2299 ALOGV("%s:napb: not in true mode or non hdphones device",
2300 __func__);
2301 active = false;
2302 goto exit;
2303 }
2304
2305 list_for_each(node, &adev->usecase_list) {
2306 struct audio_usecase *uc;
2307 uc = node_to_item(node, struct audio_usecase, list);
2308 struct stream_out *curr_out =
2309 (struct stream_out*) uc->stream.out;
2310
2311 if (curr_out && PCM_PLAYBACK == uc->type) {
2312 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2313 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2314 uc->id, curr_out->sample_rate,
2315 curr_out->bit_width,
2316 platform_get_snd_device_name(uc->out_snd_device));
2317
2318 if (is_offload_usecase(uc->id) &&
2319 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2320 active = true;
2321 ALOGD("%s:napb:native stream detected", __func__);
2322 }
2323 }
2324 }
2325exit:
2326 return active;
2327}
2328
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002329uint32_t adev_get_dsp_bit_width_enforce_mode()
2330{
2331 if (adev == NULL) {
2332 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2333 return 0;
2334 }
2335 return adev->dsp_bit_width_enforce_mode;
2336}
2337
2338static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2339{
2340 char value[PROPERTY_VALUE_MAX];
2341 int trial;
2342 uint32_t dsp_bit_width_enforce_mode = 0;
2343
2344 if (!mixer) {
2345 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2346 __func__);
2347 return 0;
2348 }
2349
2350 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2351 value, NULL) > 0) {
2352 trial = atoi(value);
2353 switch (trial) {
2354 case 16:
2355 dsp_bit_width_enforce_mode = 16;
2356 break;
2357 case 24:
2358 dsp_bit_width_enforce_mode = 24;
2359 break;
2360 case 32:
2361 dsp_bit_width_enforce_mode = 32;
2362 break;
2363 default:
2364 dsp_bit_width_enforce_mode = 0;
2365 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2366 break;
2367 }
2368 }
2369
2370 return dsp_bit_width_enforce_mode;
2371}
2372
2373static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2374 uint32_t enforce_mode,
2375 bool enable)
2376{
2377 struct mixer_ctl *ctl = NULL;
2378 const char *mixer_ctl_name = "ASM Bit Width";
2379 uint32_t asm_bit_width_mode = 0;
2380
2381 if (enforce_mode == 0) {
2382 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2383 return;
2384 }
2385
2386 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2387 if (!ctl) {
2388 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2389 __func__, mixer_ctl_name);
2390 return;
2391 }
2392
2393 if (enable)
2394 asm_bit_width_mode = enforce_mode;
2395 else
2396 asm_bit_width_mode = 0;
2397
2398 ALOGV("%s DSP bit width feature status is %d width=%d",
2399 __func__, enable, asm_bit_width_mode);
2400 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2401 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2402 asm_bit_width_mode);
2403
2404 return;
2405}
2406
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302407/*
2408 * if native DSD playback active
2409 */
2410bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2411{
2412 bool active = false;
2413 struct listnode *node = NULL;
2414 struct audio_usecase *uc = NULL;
2415 struct stream_out *curr_out = NULL;
2416
2417 list_for_each(node, &adev->usecase_list) {
2418 uc = node_to_item(node, struct audio_usecase, list);
2419 curr_out = (struct stream_out*) uc->stream.out;
2420
2421 if (curr_out && PCM_PLAYBACK == uc->type &&
2422 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2423 active = true;
2424 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302425 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302426 }
2427 }
2428 return active;
2429}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302430
2431static bool force_device_switch(struct audio_usecase *usecase)
2432{
2433 bool ret = false;
2434 bool is_it_true_mode = false;
2435
Zhou Song30f2c3e2018-02-08 14:02:15 +08002436 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302437 usecase->type == TRANSCODE_LOOPBACK_RX ||
2438 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002439 return false;
2440 }
2441
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002442 if(usecase->stream.out == NULL) {
2443 ALOGE("%s: stream.out is NULL", __func__);
2444 return false;
2445 }
2446
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302447 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002448 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002449 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2450 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302451 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2452 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2453 (!is_it_true_mode && adev->native_playback_enabled)){
2454 ret = true;
2455 ALOGD("napb: time to toggle native mode");
2456 }
2457 }
2458
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302459 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302460 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2461 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002462 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302463 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302464 ALOGD("Force a2dp device switch to update new encoder config");
2465 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002466 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302467
Florian Pfister1a84f312018-07-19 14:38:18 +02002468 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302469 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2470 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002471 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302472 return ret;
2473}
2474
Aalique Grahame22e49102018-12-18 14:23:57 -08002475static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2476{
2477 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2478}
2479
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302480bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2481{
2482 bool ret=false;
2483 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002484 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2485 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302486 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2487 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002488 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302489 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002490 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2491 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302492 ret = true;
2493
2494 return ret;
2495}
2496
2497bool is_a2dp_device(snd_device_t out_snd_device)
2498{
2499 bool ret=false;
2500 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2501 ret = true;
2502
2503 return ret;
2504}
2505
2506bool is_bt_soc_on(struct audio_device *adev)
2507{
2508 struct mixer_ctl *ctl;
2509 char *mixer_ctl_name = "BT SOC status";
2510 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2511 bool bt_soc_status = true;
2512 if (!ctl) {
2513 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2514 __func__, mixer_ctl_name);
2515 /*This is to ensure we dont break targets which dont have the kernel change*/
2516 return true;
2517 }
2518 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2519 ALOGD("BT SOC status: %d",bt_soc_status);
2520 return bt_soc_status;
2521}
2522
Zhou Song331c8e52019-08-26 14:16:12 +08002523static int configure_btsco_sample_rate(snd_device_t snd_device)
2524{
2525 struct mixer_ctl *ctl = NULL;
2526 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2527 char *rate_str = NULL;
2528 bool is_rx_dev = true;
2529
2530 if (is_btsco_device(snd_device, snd_device)) {
2531 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2532 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2533 if (!ctl_sr_tx || !ctl_sr_rx) {
2534 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2535 if (!ctl_sr)
2536 return -ENOSYS;
2537 }
2538
2539 switch (snd_device) {
2540 case SND_DEVICE_OUT_BT_SCO:
2541 rate_str = "KHZ_8";
2542 break;
2543 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2544 case SND_DEVICE_IN_BT_SCO_MIC:
2545 rate_str = "KHZ_8";
2546 is_rx_dev = false;
2547 break;
2548 case SND_DEVICE_OUT_BT_SCO_WB:
2549 rate_str = "KHZ_16";
2550 break;
2551 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2552 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2553 rate_str = "KHZ_16";
2554 is_rx_dev = false;
2555 break;
2556 default:
2557 return 0;
2558 }
2559
2560 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2561 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2562 return -ENOSYS;
2563 }
2564 return 0;
2565}
2566
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302567int out_standby_l(struct audio_stream *stream);
2568
Eric Laurent637e2d42018-11-15 12:24:31 -08002569struct stream_in *adev_get_active_input(const struct audio_device *adev)
2570{
2571 struct listnode *node;
2572 struct stream_in *last_active_in = NULL;
2573
2574 /* Get last added active input.
2575 * TODO: We may use a priority mechanism to pick highest priority active source */
2576 list_for_each(node, &adev->usecase_list)
2577 {
2578 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2579 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2580 last_active_in = usecase->stream.in;
2581 }
2582
2583 return last_active_in;
2584}
2585
2586struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2587{
2588 struct listnode *node;
2589
2590 /* First check active inputs with voice communication source and then
2591 * any input if audio mode is in communication */
2592 list_for_each(node, &adev->usecase_list)
2593 {
2594 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2595 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2596 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2597 return usecase->stream.in;
2598 }
2599 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2600 return adev_get_active_input(adev);
2601
2602 return NULL;
2603}
2604
Carter Hsu2e429db2019-05-14 18:50:52 +08002605/*
2606 * Aligned with policy.h
2607 */
2608static inline int source_priority(int inputSource)
2609{
2610 switch (inputSource) {
2611 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2612 return 9;
2613 case AUDIO_SOURCE_CAMCORDER:
2614 return 8;
2615 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2616 return 7;
2617 case AUDIO_SOURCE_UNPROCESSED:
2618 return 6;
2619 case AUDIO_SOURCE_MIC:
2620 return 5;
2621 case AUDIO_SOURCE_ECHO_REFERENCE:
2622 return 4;
2623 case AUDIO_SOURCE_FM_TUNER:
2624 return 3;
2625 case AUDIO_SOURCE_VOICE_RECOGNITION:
2626 return 2;
2627 case AUDIO_SOURCE_HOTWORD:
2628 return 1;
2629 default:
2630 break;
2631 }
2632 return 0;
2633}
2634
2635static struct stream_in *get_priority_input(struct audio_device *adev)
2636{
2637 struct listnode *node;
2638 struct audio_usecase *usecase;
2639 int last_priority = 0, priority;
2640 struct stream_in *priority_in = NULL;
2641 struct stream_in *in;
2642
2643 list_for_each(node, &adev->usecase_list) {
2644 usecase = node_to_item(node, struct audio_usecase, list);
2645 if (usecase->type == PCM_CAPTURE) {
2646 in = usecase->stream.in;
2647 if (!in)
2648 continue;
2649 priority = source_priority(in->source);
2650
2651 if (priority > last_priority) {
2652 last_priority = priority;
2653 priority_in = in;
2654 }
2655 }
2656 }
2657 return priority_in;
2658}
2659
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002660int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002662 snd_device_t out_snd_device = SND_DEVICE_NONE;
2663 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002664 struct audio_usecase *usecase = NULL;
2665 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002666 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002667 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302668 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002669 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002670 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302672 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2673
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002674 usecase = get_usecase_from_list(adev, uc_id);
2675 if (usecase == NULL) {
2676 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2677 return -EINVAL;
2678 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002680 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002681 (usecase->type == VOIP_CALL) ||
2682 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302683 if(usecase->stream.out == NULL) {
2684 ALOGE("%s: stream.out is NULL", __func__);
2685 return -EINVAL;
2686 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002687 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002688 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2689 uc_id);
2690 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2691 uc_id);
2692 } else {
2693 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302694 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002695 in_snd_device = platform_get_input_snd_device(adev->platform,
2696 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302697 &usecase->stream.out->device_list,
2698 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002699 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002700 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302701 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302702 if (usecase->stream.inout == NULL) {
2703 ALOGE("%s: stream.inout is NULL", __func__);
2704 return -EINVAL;
2705 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002706 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302707 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2708 stream_out.format = usecase->stream.inout->out_config.format;
2709 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302710 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002711 assign_devices(&usecase->device_list,
2712 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302713 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2714 if (usecase->stream.inout == NULL) {
2715 ALOGE("%s: stream.inout is NULL", __func__);
2716 return -EINVAL;
2717 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302718 struct listnode out_devices;
2719 list_init(&out_devices);
2720 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2721 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002722 assign_devices(&usecase->device_list,
2723 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002724 } else {
2725 /*
2726 * If the voice call is active, use the sound devices of voice call usecase
2727 * so that it would not result any device switch. All the usecases will
2728 * be switched to new device when select_devices() is called for voice call
2729 * usecase. This is to avoid switching devices for voice call when
2730 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002731 * choose voice call device only if the use case device is
2732 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002734 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002735 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002736 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002737 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2738 is_codec_backend_out_device_type(&usecase->device_list)) ||
2739 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2740 is_codec_backend_in_device_type(&usecase->device_list)) ||
2741 is_single_device_type_equal(&vc_usecase->device_list,
2742 AUDIO_DEVICE_OUT_HEARING_AID) ||
2743 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002744 AUDIO_DEVICE_IN_VOICE_CALL) ||
2745 (is_single_device_type_equal(&usecase->device_list,
2746 AUDIO_DEVICE_IN_USB_HEADSET) &&
2747 is_single_device_type_equal(&vc_usecase->device_list,
2748 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002749 in_snd_device = vc_usecase->in_snd_device;
2750 out_snd_device = vc_usecase->out_snd_device;
2751 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002752 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002753 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002754 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002755 if ((voip_usecase != NULL) &&
2756 (usecase->type == PCM_PLAYBACK) &&
2757 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002758 out_snd_device_backend_match = platform_check_backends_match(
2759 voip_usecase->out_snd_device,
2760 platform_get_output_snd_device(
2761 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302762 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002763 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002764 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2765 (is_codec_backend_out_device_type(&usecase->device_list) ||
2766 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002767 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002768 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002769 in_snd_device = voip_usecase->in_snd_device;
2770 out_snd_device = voip_usecase->out_snd_device;
2771 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002772 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002773 hfp_ucid = audio_extn_hfp_get_usecase();
2774 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002775 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002776 in_snd_device = hfp_usecase->in_snd_device;
2777 out_snd_device = hfp_usecase->out_snd_device;
2778 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002779 }
2780 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302781 if (usecase->stream.out == NULL) {
2782 ALOGE("%s: stream.out is NULL", __func__);
2783 return -EINVAL;
2784 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002785 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002786 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002787 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002788 struct stream_out *voip_out = adev->primary_output;
2789 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002791 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2792 else
2793 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302794 usecase->stream.out,
2795 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002796 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002797
Eric Laurent637e2d42018-11-15 12:24:31 -08002798 if (voip_usecase)
2799 voip_out = voip_usecase->stream.out;
2800
2801 if (usecase->stream.out == voip_out && voip_in != NULL)
2802 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002803 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002804 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302805 if (usecase->stream.in == NULL) {
2806 ALOGE("%s: stream.in is NULL", __func__);
2807 return -EINVAL;
2808 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002809 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002810 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002811 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002812 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002813 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002814 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002815
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002816 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002817 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002818 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2819 USECASE_AUDIO_PLAYBACK_VOIP);
2820
Carter Hsu2e429db2019-05-14 18:50:52 +08002821 usecase->stream.in->enable_ec_port = false;
2822
Zhou Song62ea0282020-03-22 19:53:01 +08002823 bool is_ha_usecase = adev->ha_proxy_enable ?
2824 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2825 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2826 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002827 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002828 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002829 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002830 } else if (adev->primary_output &&
2831 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002832 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002833 } else {
2834 /* forcing speaker o/p device to get matching i/p pair
2835 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002836 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002837 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002838 priority_in = voip_in;
2839 } else {
2840 /* get the input with the highest priority source*/
2841 priority_in = get_priority_input(adev);
2842
2843 if (!priority_in)
2844 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002845 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002846
Eric Laurent637e2d42018-11-15 12:24:31 -08002847 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002848 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302849 &out_devices,
2850 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 }
2853 }
2854
2855 if (out_snd_device == usecase->out_snd_device &&
2856 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302857
2858 if (!force_device_switch(usecase))
2859 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 }
2861
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002862 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002863 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002864 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002865 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2866 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302867 }
2868
Aalique Grahame22e49102018-12-18 14:23:57 -08002869 if (out_snd_device != SND_DEVICE_NONE &&
2870 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2871 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2872 __func__,
2873 use_case_table[uc_id],
2874 adev->last_logged_snd_device[uc_id][0],
2875 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2876 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2877 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2878 -1,
2879 out_snd_device,
2880 platform_get_snd_device_name(out_snd_device),
2881 platform_get_snd_device_acdb_id(out_snd_device));
2882 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2883 }
2884 if (in_snd_device != SND_DEVICE_NONE &&
2885 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2886 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2887 __func__,
2888 use_case_table[uc_id],
2889 adev->last_logged_snd_device[uc_id][1],
2890 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2891 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2892 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2893 -1,
2894 in_snd_device,
2895 platform_get_snd_device_name(in_snd_device),
2896 platform_get_snd_device_acdb_id(in_snd_device));
2897 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2898 }
2899
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 /*
2902 * Limitation: While in call, to do a device switch we need to disable
2903 * and enable both RX and TX devices though one of them is same as current
2904 * device.
2905 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002906 if ((usecase->type == VOICE_CALL) &&
2907 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2908 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002909 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002910 }
2911
2912 if (((usecase->type == VOICE_CALL) ||
2913 (usecase->type == VOIP_CALL)) &&
2914 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2915 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302916 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002917 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002918 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002919
2920 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302921 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002922 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002923 }
2924
Aalique Grahame22e49102018-12-18 14:23:57 -08002925 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2926 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002927 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302928 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002929 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2930 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2931 else
2932 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302933 }
2934
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002935 /* Disable current sound devices */
2936 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002937 disable_audio_route(adev, usecase);
2938 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 }
2940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002941 if (usecase->in_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->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 }
2945
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002946 /* Applicable only on the targets that has external modem.
2947 * New device information should be sent to modem before enabling
2948 * the devices to reduce in-call device switch time.
2949 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002950 if ((usecase->type == VOICE_CALL) &&
2951 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2952 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002953 status = platform_switch_voice_call_enable_device_config(adev->platform,
2954 out_snd_device,
2955 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002956 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002957
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002958 /* Enable new sound devices */
2959 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002960 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302961 if (platform_check_codec_asrc_support(adev->platform))
2962 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002963 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 }
2965
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002966 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302967 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002968 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002969 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002970
Avinash Vaish71a8b972014-07-24 15:36:33 +05302971 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002972 status = platform_switch_voice_call_device_post(adev->platform,
2973 out_snd_device,
2974 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302975 enable_audio_route_for_voice_usecases(adev, usecase);
2976 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002977
sangwoo170731f2013-06-08 15:36:36 +09002978 usecase->in_snd_device = in_snd_device;
2979 usecase->out_snd_device = out_snd_device;
2980
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302981 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2982 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302983 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002984 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002985 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002986 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2987 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2988 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2989 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2990 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2991 /*
2992 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2993 * configured device sample rate, if not update the COPP rate to be equal to the
2994 * device sample rate, else open COPP at stream sample rate
2995 */
2996 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2997 usecase->stream.out->sample_rate,
2998 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302999 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303000 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3001 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303002 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003003 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3004 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3005 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3006 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003007 }
3008 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003009
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003010 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003011
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003012 /* If input stream is already running then effect needs to be
3013 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003014 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003015 check_and_enable_effect(adev);
3016
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003017 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003018 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303019 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003020 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3021
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003022 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303023 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003024 voice_extn_compress_voip_is_started(adev))
3025 voice_set_sidetone(adev, out_snd_device, true);
3026 }
3027
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003028 /* Applicable only on the targets that has external modem.
3029 * Enable device command should be sent to modem only after
3030 * enabling voice call mixer controls
3031 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003032 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003033 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3034 out_snd_device,
3035 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303036
3037 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003038 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303039 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003040 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303041 if (is_bt_soc_on(adev) == false){
3042 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003043 if (in->pcm != NULL)
3044 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303045 }
3046 }
3047 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3048 && usecase->stream.out->started) {
3049 if (is_bt_soc_on(adev) == false) {
3050 ALOGD("BT SCO/A2DP disconnected while in connection");
3051 out_standby_l(&usecase->stream.out->stream.common);
3052 }
3053 }
3054 } else if ((usecase->stream.out != NULL) &&
3055 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303056 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3057 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003058 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303059 usecase->stream.out->started) {
3060 if (is_bt_soc_on(adev) == false) {
3061 ALOGD("BT SCO/A2dp disconnected while in connection");
3062 out_standby_l(&usecase->stream.out->stream.common);
3063 }
3064 }
3065 }
3066
Yung Ti Su70cb8242018-06-22 17:38:47 +08003067 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003068 struct stream_out *voip_out = voip_usecase->stream.out;
3069 audio_extn_utils_send_app_type_gain(adev,
3070 voip_out->app_type_cfg.app_type,
3071 &voip_out->app_type_cfg.gain[0]);
3072 }
3073
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303074 ALOGD("%s: done",__func__);
3075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 return status;
3077}
3078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079static int stop_input_stream(struct stream_in *in)
3080{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303081 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303083
3084 if (in == NULL) {
3085 ALOGE("%s: stream_in ptr is NULL", __func__);
3086 return -EINVAL;
3087 }
3088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003090 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091
Eric Laurent994a6932013-07-17 11:51:42 -07003092 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003093 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 uc_info = get_usecase_from_list(adev, in->usecase);
3095 if (uc_info == NULL) {
3096 ALOGE("%s: Could not find the usecase (%d) in the list",
3097 __func__, in->usecase);
3098 return -EINVAL;
3099 }
3100
Carter Hsu2e429db2019-05-14 18:50:52 +08003101 priority_in = get_priority_input(adev);
3102
Derek Chenea197282019-01-07 17:35:01 -08003103 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3104 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003105
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003106 /* Close in-call recording streams */
3107 voice_check_and_stop_incall_rec_usecase(adev, in);
3108
Eric Laurent150dbfe2013-02-27 14:31:02 -08003109 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003110 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003111
3112 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003113 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003115 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303116 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3117
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003118 list_remove(&uc_info->list);
3119 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120
Carter Hsu2e429db2019-05-14 18:50:52 +08003121 if (priority_in == in) {
3122 priority_in = get_priority_input(adev);
3123 if (priority_in)
3124 select_devices(adev, priority_in->usecase);
3125 }
3126
Vatsal Buchac09ae062018-11-14 13:25:08 +05303127 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003128 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 return ret;
3130}
3131
3132int start_input_stream(struct stream_in *in)
3133{
3134 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003135 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303137
3138 if (in == NULL) {
3139 ALOGE("%s: stream_in ptr is NULL", __func__);
3140 return -EINVAL;
3141 }
3142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003144 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003145 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Mingming Yin2664a5b2015-09-03 10:53:11 -07003147 if (get_usecase_from_list(adev, usecase) == NULL)
3148 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303149 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3150 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003151
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303152 if (CARD_STATUS_OFFLINE == in->card_status||
3153 CARD_STATUS_OFFLINE == adev->card_status) {
3154 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303155 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303156 goto error_config;
3157 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003159 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303160 if (!adev->bt_sco_on) {
3161 ALOGE("%s: SCO profile is not ready, return error", __func__);
3162 ret = -EIO;
3163 goto error_config;
3164 }
3165 }
3166
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003167 /* Check if source matches incall recording usecase criteria */
3168 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3169 if (ret)
3170 goto error_config;
3171 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003172 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3173
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303174 if (audio_extn_cin_attached_usecase(in))
3175 audio_extn_cin_acquire_usecase(in);
3176
Mingming Yin2664a5b2015-09-03 10:53:11 -07003177 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3178 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3179 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003180 ret = -EINVAL;
3181 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003182 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003183
Eric Laurentb23d5282013-05-14 15:27:20 -07003184 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (in->pcm_device_id < 0) {
3186 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3187 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003188 ret = -EINVAL;
3189 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003193
3194 if (!uc_info) {
3195 ret = -ENOMEM;
3196 goto error_config;
3197 }
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 uc_info->id = in->usecase;
3200 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003201 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003202 list_init(&uc_info->device_list);
3203 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003204 uc_info->in_snd_device = SND_DEVICE_NONE;
3205 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003207 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003208 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303209 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3210 adev->perf_lock_opts,
3211 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003212 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213
Derek Chenea197282019-01-07 17:35:01 -08003214 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3215 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003216
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303217 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3218
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303219 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303220 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303221 if (ret)
3222 goto error_open;
3223 else
3224 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 }
3226
Haynes Mathew George16081042017-05-31 17:16:49 -07003227 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 ALOGE("%s: pcm stream not ready", __func__);
3230 goto error_open;
3231 }
3232 ret = pcm_start(in->pcm);
3233 if (ret < 0) {
3234 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3235 goto error_open;
3236 }
3237 } else {
3238 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3239 unsigned int pcm_open_retry_count = 0;
3240
Zhou Song62ea0282020-03-22 19:53:01 +08003241 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3242 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003243 flags |= PCM_MMAP | PCM_NOIRQ;
3244 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3245 } else if (in->realtime) {
3246 flags |= PCM_MMAP | PCM_NOIRQ;
3247 }
3248
Garmond Leunge2433c32017-09-28 21:51:22 -07003249 if (audio_extn_ffv_get_stream() == in) {
3250 ALOGD("%s: ffv stream, update pcm config", __func__);
3251 audio_extn_ffv_update_pcm_config(&config);
3252 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3254 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3255
3256 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003257 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003258 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003259 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303261 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303262 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3263 adev->card_status = CARD_STATUS_OFFLINE;
3264 in->card_status = CARD_STATUS_OFFLINE;
3265 ret = -EIO;
3266 goto error_open;
3267 }
3268
Haynes Mathew George16081042017-05-31 17:16:49 -07003269 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3270 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3271 if (in->pcm != NULL) {
3272 pcm_close(in->pcm);
3273 in->pcm = NULL;
3274 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003275 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 ret = -EIO;
3277 goto error_open;
3278 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003279 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003280 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3281 continue;
3282 }
3283 break;
3284 }
3285
3286 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003287 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003288 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003289 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003290 if (ret < 0) {
3291 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3292 pcm_close(in->pcm);
3293 in->pcm = NULL;
3294 goto error_open;
3295 }
3296 register_in_stream(in);
3297 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003298 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003299 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003300 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003301 if (ret < 0) {
3302 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003303 pcm_close(in->pcm);
3304 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003305 goto error_open;
3306 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003307 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003308 }
3309
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003310 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003311 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3312 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003313
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003314 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303315 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3316
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303317done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003318 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303319 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003320 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303321 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003322 return ret;
3323
3324error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003325 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303326 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003328
Eric Laurentc8400632013-02-14 19:04:54 -08003329error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003330 if (audio_extn_cin_attached_usecase(in))
3331 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303332 /*
3333 * sleep 50ms to allow sufficient time for kernel
3334 * drivers to recover incases like SSR.
3335 */
3336 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003337 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303338 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340}
3341
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003342void lock_input_stream(struct stream_in *in)
3343{
3344 pthread_mutex_lock(&in->pre_lock);
3345 pthread_mutex_lock(&in->lock);
3346 pthread_mutex_unlock(&in->pre_lock);
3347}
3348
3349void lock_output_stream(struct stream_out *out)
3350{
3351 pthread_mutex_lock(&out->pre_lock);
3352 pthread_mutex_lock(&out->lock);
3353 pthread_mutex_unlock(&out->pre_lock);
3354}
3355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356/* must be called with out->lock locked */
3357static int send_offload_cmd_l(struct stream_out* out, int command)
3358{
3359 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3360
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003361 if (!cmd) {
3362 ALOGE("failed to allocate mem for command 0x%x", command);
3363 return -ENOMEM;
3364 }
3365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 ALOGVV("%s %d", __func__, command);
3367
3368 cmd->cmd = command;
3369 list_add_tail(&out->offload_cmd_list, &cmd->node);
3370 pthread_cond_signal(&out->offload_cond);
3371 return 0;
3372}
3373
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003374/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375static void stop_compressed_output_l(struct stream_out *out)
3376{
3377 out->offload_state = OFFLOAD_STATE_IDLE;
3378 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003379 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 if (out->compr != NULL) {
3381 compress_stop(out->compr);
3382 while (out->offload_thread_blocked) {
3383 pthread_cond_wait(&out->cond, &out->lock);
3384 }
3385 }
3386}
3387
Varun Balaraje49253e2017-07-06 19:48:56 +05303388bool is_interactive_usecase(audio_usecase_t uc_id)
3389{
3390 unsigned int i;
3391 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3392 if (uc_id == interactive_usecases[i])
3393 return true;
3394 }
3395 return false;
3396}
3397
3398static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3399{
3400 audio_usecase_t ret_uc = USECASE_INVALID;
3401 unsigned int intract_uc_index;
3402 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3403
3404 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3405 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3406 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3407 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3408 ret_uc = interactive_usecases[intract_uc_index];
3409 break;
3410 }
3411 }
3412
3413 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3414 return ret_uc;
3415}
3416
3417static void free_interactive_usecase(struct audio_device *adev,
3418 audio_usecase_t uc_id)
3419{
3420 unsigned int interact_uc_index;
3421 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3422
3423 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3424 if (interactive_usecases[interact_uc_index] == uc_id) {
3425 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3426 break;
3427 }
3428 }
3429 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3430}
3431
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003432bool is_offload_usecase(audio_usecase_t uc_id)
3433{
3434 unsigned int i;
3435 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3436 if (uc_id == offload_usecases[i])
3437 return true;
3438 }
3439 return false;
3440}
3441
Dhananjay Kumarac341582017-02-23 23:42:25 +05303442static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003443{
vivek mehta446c3962015-09-14 10:57:35 -07003444 audio_usecase_t ret_uc = USECASE_INVALID;
3445 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003446 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003447 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303448 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003449 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3450 else
3451 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003452
vivek mehta446c3962015-09-14 10:57:35 -07003453 pthread_mutex_lock(&adev->lock);
3454 if (get_usecase_from_list(adev, ret_uc) != NULL)
3455 ret_uc = USECASE_INVALID;
3456 pthread_mutex_unlock(&adev->lock);
3457
3458 return ret_uc;
3459 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003460
3461 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003462 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3463 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3464 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3465 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003466 break;
3467 }
3468 }
vivek mehta446c3962015-09-14 10:57:35 -07003469
3470 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3471 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003472}
3473
3474static void free_offload_usecase(struct audio_device *adev,
3475 audio_usecase_t uc_id)
3476{
vivek mehta446c3962015-09-14 10:57:35 -07003477 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003478 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003479
3480 if (!adev->multi_offload_enable)
3481 return;
3482
3483 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3484 if (offload_usecases[offload_uc_index] == uc_id) {
3485 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003486 break;
3487 }
3488 }
3489 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3490}
3491
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492static void *offload_thread_loop(void *context)
3493{
3494 struct stream_out *out = (struct stream_out *) context;
3495 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003496 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003499 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3501
3502 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003503 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003504 out->offload_state = OFFLOAD_STATE_IDLE;
3505 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 for (;;) {
3507 struct offload_cmd *cmd = NULL;
3508 stream_callback_event_t event;
3509 bool send_callback = false;
3510
3511 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3512 __func__, list_empty(&out->offload_cmd_list),
3513 out->offload_state);
3514 if (list_empty(&out->offload_cmd_list)) {
3515 ALOGV("%s SLEEPING", __func__);
3516 pthread_cond_wait(&out->offload_cond, &out->lock);
3517 ALOGV("%s RUNNING", __func__);
3518 continue;
3519 }
3520
3521 item = list_head(&out->offload_cmd_list);
3522 cmd = node_to_item(item, struct offload_cmd, node);
3523 list_remove(item);
3524
3525 ALOGVV("%s STATE %d CMD %d out->compr %p",
3526 __func__, out->offload_state, cmd->cmd, out->compr);
3527
3528 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3529 free(cmd);
3530 break;
3531 }
3532
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003533 // allow OFFLOAD_CMD_ERROR reporting during standby
3534 // this is needed to handle failures during compress_open
3535 // Note however that on a pause timeout, the stream is closed
3536 // and no offload usecase will be active. Therefore this
3537 // special case is needed for compress_open failures alone
3538 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3539 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003541 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542 pthread_cond_signal(&out->cond);
3543 continue;
3544 }
3545 out->offload_thread_blocked = true;
3546 pthread_mutex_unlock(&out->lock);
3547 send_callback = false;
3548 switch(cmd->cmd) {
3549 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003550 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003552 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 send_callback = true;
3554 event = STREAM_CBK_EVENT_WRITE_READY;
3555 break;
3556 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003557 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303558 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003559 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303560 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003561 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303562 if (ret < 0)
3563 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303564 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303565 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003566 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003567 else
3568 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003569 if (-ENETRESET != ret && !(-EINTR == ret &&
3570 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303571 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303572 pthread_mutex_lock(&out->lock);
3573 out->send_new_metadata = 1;
3574 out->send_next_track_params = true;
3575 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303576 event = STREAM_CBK_EVENT_DRAIN_READY;
3577 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3578 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303579 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 break;
3581 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003582 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003583 ret = compress_drain(out->compr);
3584 ALOGD("copl(%p):out of compress_drain", out);
3585 // EINTR check avoids drain interruption due to SSR
3586 if (-ENETRESET != ret && !(-EINTR == ret &&
3587 CARD_STATUS_OFFLINE == out->card_status)) {
3588 send_callback = true;
3589 event = STREAM_CBK_EVENT_DRAIN_READY;
3590 } else
3591 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003592 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303593 case OFFLOAD_CMD_ERROR:
3594 ALOGD("copl(%p): sending error callback to AF", out);
3595 send_callback = true;
3596 event = STREAM_CBK_EVENT_ERROR;
3597 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003598 default:
3599 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3600 break;
3601 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003602 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603 out->offload_thread_blocked = false;
3604 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003605 if (send_callback && out->client_callback) {
3606 ALOGVV("%s: sending client_callback event %d", __func__, event);
3607 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003608 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 free(cmd);
3610 }
3611
3612 pthread_cond_signal(&out->cond);
3613 while (!list_empty(&out->offload_cmd_list)) {
3614 item = list_head(&out->offload_cmd_list);
3615 list_remove(item);
3616 free(node_to_item(item, struct offload_cmd, node));
3617 }
3618 pthread_mutex_unlock(&out->lock);
3619
3620 return NULL;
3621}
3622
3623static int create_offload_callback_thread(struct stream_out *out)
3624{
3625 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3626 list_init(&out->offload_cmd_list);
3627 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3628 offload_thread_loop, out);
3629 return 0;
3630}
3631
3632static int destroy_offload_callback_thread(struct stream_out *out)
3633{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003634 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003635 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003636 stop_compressed_output_l(out);
3637 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3638
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003639 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003640 pthread_mutex_unlock(&out->lock);
3641 pthread_join(out->offload_thread, (void **) NULL);
3642 pthread_cond_destroy(&out->offload_cond);
3643
3644 return 0;
3645}
3646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647static int stop_output_stream(struct stream_out *out)
3648{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303649 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 struct audio_usecase *uc_info;
3651 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003652 bool has_voip_usecase =
3653 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654
Eric Laurent994a6932013-07-17 11:51:42 -07003655 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003656 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 uc_info = get_usecase_from_list(adev, out->usecase);
3658 if (uc_info == NULL) {
3659 ALOGE("%s: Could not find the usecase (%d) in the list",
3660 __func__, out->usecase);
3661 return -EINVAL;
3662 }
3663
Derek Chenea197282019-01-07 17:35:01 -08003664 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3665 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003666
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003667 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303668 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003669 if (adev->visualizer_stop_output != NULL)
3670 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003671
3672 audio_extn_dts_remove_state_notifier_node(out->usecase);
3673
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003674 if (adev->offload_effects_stop_output != NULL)
3675 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003676 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3677 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3678 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003679 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003680
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003681 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3682 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003683 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003684 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003685
Eric Laurent150dbfe2013-02-27 14:31:02 -08003686 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003687 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003688
3689 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003690 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
Aalique Grahame22e49102018-12-18 14:23:57 -08003692 audio_extn_extspk_update(adev->extspk);
3693
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003694 if (is_offload_usecase(out->usecase)) {
3695 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3696 adev->dsp_bit_width_enforce_mode,
3697 false);
3698 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003699 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003700 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3701 false);
3702
3703 if (ret != 0)
3704 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3705 /* default service interval was successfully updated,
3706 reopen USB backend with new service interval */
3707 ret = 0;
3708 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003709
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003710 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303711 out->started = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003712 pthread_mutex_lock(&out->latch_lock);
3713 out->muted = false;
3714 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003715 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303716 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003717 ALOGV("Disable passthrough , reset mixer to pcm");
3718 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003719#ifdef AUDIO_GKI_ENABLED
3720 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3721 out->compr_config.codec->reserved[0] = 0;
3722#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003723 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003724#endif
Mingming Yin21854652016-04-13 11:54:02 -07003725 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003726 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3727 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003728
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303729 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003730 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303731 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303732
Manish Dewangan21a850a2017-08-14 12:03:55 +05303733 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003734 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3735 if (ret < 0)
3736 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3737 }
3738
juyuchen2d415992018-11-16 14:15:16 +08003739 /* 1) media + voip output routing to handset must route media back to
3740 speaker when voip stops.
3741 2) trigger voip input to reroute when voip output changes to
3742 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003743 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003744 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003745 struct listnode *node;
3746 struct audio_usecase *usecase;
3747 list_for_each(node, &adev->usecase_list) {
3748 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003749 if ((usecase->type == PCM_CAPTURE &&
3750 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3751 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003752 continue;
3753
3754 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3755 __func__, usecase->id, use_case_table[usecase->id],
3756 out->usecase, use_case_table[out->usecase]);
3757 select_devices(adev, usecase->id);
3758 }
3759 }
3760
Garmond Leung5fd0b552018-04-17 11:56:12 -07003761 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003762 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 return ret;
3764}
3765
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003766struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3767 unsigned int flags, unsigned int pcm_open_retry_count,
3768 struct pcm_config *config)
3769{
3770 struct pcm* pcm = NULL;
3771
3772 while (1) {
3773 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3774 if (pcm == NULL || !pcm_is_ready(pcm)) {
3775 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3776 if (pcm != NULL) {
3777 pcm_close(pcm);
3778 pcm = NULL;
3779 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003780 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003781 return NULL;
3782
Weiyin Jiang72197252019-10-09 11:49:32 +08003783 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003784 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3785 continue;
3786 }
3787 break;
3788 }
3789
3790 if (pcm_is_ready(pcm)) {
3791 int ret = pcm_prepare(pcm);
3792 if (ret < 0) {
3793 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3794 pcm_close(pcm);
3795 pcm = NULL;
3796 }
3797 }
3798
3799 return pcm;
3800}
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802int start_output_stream(struct stream_out *out)
3803{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 struct audio_usecase *uc_info;
3806 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003807 char mixer_ctl_name[128];
3808 struct mixer_ctl *ctl = NULL;
3809 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303810 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003811 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812
Haynes Mathew George380745d2017-10-04 15:27:45 -07003813 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003814 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3815 ret = -EINVAL;
3816 goto error_config;
3817 }
3818
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003819 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303820 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003821 get_device_types(&out->device_list), is_haptic_usecase);
3822
3823 bool is_speaker_active = compare_device_type(&out->device_list,
3824 AUDIO_DEVICE_OUT_SPEAKER);
3825 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3826 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303827
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303828 if (CARD_STATUS_OFFLINE == out->card_status ||
3829 CARD_STATUS_OFFLINE == adev->card_status) {
3830 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303831 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003832 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303833 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303834
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003835 //Update incall music usecase to reflect correct voice session
3836 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3837 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3838 if (ret != 0) {
3839 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3840 __func__, ret);
3841 goto error_config;
3842 }
3843 }
3844
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003845 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003846 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003847 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303848 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303849 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303850 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3851 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3852 ret = -EAGAIN;
3853 goto error_config;
3854 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303855 }
3856 }
3857 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003858 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303859 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003860 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303861 //combo usecase just by pass a2dp
3862 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003863 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303864 } else {
3865 ALOGE("%s: SCO profile is not ready, return error", __func__);
3866 ret = -EAGAIN;
3867 goto error_config;
3868 }
3869 }
3870 }
3871
Eric Laurentb23d5282013-05-14 15:27:20 -07003872 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873 if (out->pcm_device_id < 0) {
3874 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3875 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003876 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003877 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 }
3879
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003880 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003881 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3882 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003883 if (adev->haptic_pcm_device_id < 0) {
3884 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3885 __func__, adev->haptic_pcm_device_id, out->usecase);
3886 ret = -EINVAL;
3887 goto error_config;
3888 }
3889 }
3890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003892
3893 if (!uc_info) {
3894 ret = -ENOMEM;
3895 goto error_config;
3896 }
3897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 uc_info->id = out->usecase;
3899 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003900 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003901 list_init(&uc_info->device_list);
3902 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003903 uc_info->in_snd_device = SND_DEVICE_NONE;
3904 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003905
3906 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003907 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003908 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3909 /* USB backend is not reopened immediately.
3910 This is eventually done as part of select_devices */
3911 }
3912
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003913 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914
Wei Wangf7ca6c92017-11-21 14:51:20 -08003915 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303916 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3917 adev->perf_lock_opts,
3918 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303919
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003920 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303921 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303922 if (audio_extn_passthru_is_enabled() &&
3923 audio_extn_passthru_is_passthrough_stream(out)) {
3924 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303925 }
3926 }
3927
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003928 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003929 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303930 if (!a2dp_combo) {
3931 check_a2dp_restore_l(adev, out, false);
3932 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003933 struct listnode dev;
3934 list_init(&dev);
3935 assign_devices(&dev, &out->device_list);
3936 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3937 reassign_device_list(&out->device_list,
3938 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003939 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003940 reassign_device_list(&out->device_list,
3941 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303942 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003943 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303944 }
3945 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303946 select_devices(adev, out->usecase);
3947 if (is_a2dp_out_device_type(&out->device_list) &&
3948 !adev->a2dp_started) {
3949 if (is_speaker_active || is_speaker_safe_active) {
3950 struct listnode dev;
3951 list_init(&dev);
3952 assign_devices(&dev, &out->device_list);
3953 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3954 reassign_device_list(&out->device_list,
3955 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3956 else
3957 reassign_device_list(&out->device_list,
3958 AUDIO_DEVICE_OUT_SPEAKER, "");
3959 select_devices(adev, out->usecase);
3960 assign_devices(&out->device_list, &dev);
3961 } else {
3962 ret = -EINVAL;
3963 goto error_open;
3964 }
3965 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303966 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003967
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003968 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3969 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003970 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003971 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003972
Derek Chenea197282019-01-07 17:35:01 -08003973 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3974 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003975
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003976 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3977 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003978
3979 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003980 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003981 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3982 ALOGE("%s: pcm stream not ready", __func__);
3983 goto error_open;
3984 }
3985 ret = pcm_start(out->pcm);
3986 if (ret < 0) {
3987 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3988 goto error_open;
3989 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003990 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003991 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003992 unsigned int flags = PCM_OUT;
3993 unsigned int pcm_open_retry_count = 0;
3994 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3995 flags |= PCM_MMAP | PCM_NOIRQ;
3996 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003997 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003998 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003999 } else
4000 flags |= PCM_MONOTONIC;
4001
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004002 if ((adev->vr_audio_mode_enabled) &&
4003 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4004 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4005 "PCM_Dev %d Topology", out->pcm_device_id);
4006 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4007 if (!ctl) {
4008 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4009 __func__, mixer_ctl_name);
4010 } else {
4011 //if success use ULLPP
4012 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4013 __func__, mixer_ctl_name, out->pcm_device_id);
4014 //There is a still a possibility that some sessions
4015 // that request for FAST|RAW when 3D audio is active
4016 //can go through ULLPP. Ideally we expects apps to
4017 //listen to audio focus and stop concurrent playback
4018 //Also, we will look for mode flag (voice_in_communication)
4019 //before enabling the realtime flag.
4020 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4021 }
4022 }
4023
Surendar Karka91fa3682018-07-02 18:12:12 +05304024 if (out->realtime)
4025 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4026 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4027
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004028 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4029 flags, pcm_open_retry_count,
4030 &(out->config));
4031 if (out->pcm == NULL) {
4032 ret = -EIO;
4033 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004034 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004035
4036 if (is_haptic_usecase) {
4037 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4038 adev->haptic_pcm_device_id,
4039 flags, pcm_open_retry_count,
4040 &(adev->haptics_config));
4041 // failure to open haptics pcm shouldnt stop audio,
4042 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004043
4044 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4045 ALOGD("%s: enable haptic audio synchronization", __func__);
4046 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4047 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004048 }
4049
Surendar Karka91fa3682018-07-02 18:12:12 +05304050 if (!out->realtime)
4051 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304052 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004053
Zhou Song2b8f28f2017-09-11 10:51:38 +08004054 // apply volume for voip playback after path is set up
4055 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4056 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304057 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4058 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304059 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4060 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004061 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4062 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304063 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004064 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004065 /*
4066 * set custom channel map if:
4067 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4068 * 2. custom channel map has been set by client
4069 * else default channel map of FC/FR/FL can always be set to DSP
4070 */
4071 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4072 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4073 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004074 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4075 adev->dsp_bit_width_enforce_mode,
4076 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004078 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004079 out->compr = compress_open(adev->snd_card,
4080 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004081 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004082 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304083 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304084 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4085 adev->card_status = CARD_STATUS_OFFLINE;
4086 out->card_status = CARD_STATUS_OFFLINE;
4087 ret = -EIO;
4088 goto error_open;
4089 }
4090
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004091 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004092 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004093 compress_close(out->compr);
4094 out->compr = NULL;
4095 ret = -EIO;
4096 goto error_open;
4097 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304098 /* compress_open sends params of the track, so reset the flag here */
4099 out->is_compr_metadata_avail = false;
4100
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004101 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004102 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004103
Fred Oh3f43e742015-03-04 18:42:34 -08004104 /* Since small bufs uses blocking writes, a write will be blocked
4105 for the default max poll time (20s) in the event of an SSR.
4106 Reduce the poll time to observe and deal with SSR faster.
4107 */
Ashish Jain5106d362016-05-11 19:23:33 +05304108 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004109 compress_set_max_poll_wait(out->compr, 1000);
4110 }
4111
Manish Dewangan69426c82017-01-30 17:35:36 +05304112 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304113 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304114
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004115 audio_extn_dts_create_state_notifier_node(out->usecase);
4116 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4117 popcount(out->channel_mask),
4118 out->playback_started);
4119
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004120#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304121 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004122 audio_extn_dolby_send_ddp_endp_params(adev);
4123#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304124 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4125 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004126 if (adev->visualizer_start_output != NULL)
4127 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4128 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304129 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004130 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004131 }
Derek Chenf13dd492018-11-13 14:53:51 -08004132
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004133 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004134 /* Update cached volume from media to offload/direct stream */
4135 struct listnode *node = NULL;
4136 list_for_each(node, &adev->active_outputs_list) {
4137 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4138 streams_output_ctxt_t,
4139 list);
4140 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4141 out->volume_l = out_ctxt->output->volume_l;
4142 out->volume_r = out_ctxt->output->volume_r;
4143 }
4144 }
4145 out_set_compr_volume(&out->stream,
4146 out->volume_l, out->volume_r);
4147 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004149
4150 if (ret == 0) {
4151 register_out_stream(out);
4152 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004153 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4154 ALOGE("%s: pcm stream not ready", __func__);
4155 goto error_open;
4156 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004157 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004158 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004159 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004160 if (ret < 0)
4161 goto error_open;
4162 }
4163 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004164 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304165 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004166 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004167
vivek mehtad15d2bf2019-05-17 13:35:10 -07004168 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4169 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4170 audio_low_latency_hint_start();
4171 }
4172
Manish Dewangan21a850a2017-08-14 12:03:55 +05304173 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004174 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004175 if (ret < 0)
4176 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4177 }
4178
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004179 // consider a scenario where on pause lower layers are tear down.
4180 // so on resume, swap mixer control need to be sent only when
4181 // backend is active, hence rather than sending from enable device
4182 // sending it from start of streamtream
4183
4184 platform_set_swap_channels(adev, true);
4185
Haynes Mathew George380745d2017-10-04 15:27:45 -07004186 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304187 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004188 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004189error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004190 if (adev->haptic_pcm) {
4191 pcm_close(adev->haptic_pcm);
4192 adev->haptic_pcm = NULL;
4193 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004194 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304195 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004197error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304198 /*
4199 * sleep 50ms to allow sufficient time for kernel
4200 * drivers to recover incases like SSR.
4201 */
4202 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004203error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004204 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304205 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004206 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207}
4208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209static int check_input_parameters(uint32_t sample_rate,
4210 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004211 int channel_count,
4212 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004214 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304216 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4217 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4218 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004219 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004220 !audio_extn_compr_cap_format_supported(format) &&
4221 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004222 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004223
Aalique Grahame22e49102018-12-18 14:23:57 -08004224 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4225 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4226 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4227 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4228 return -EINVAL;
4229 }
4230
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004231 switch (channel_count) {
4232 case 1:
4233 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304234 case 3:
4235 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004236 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004237 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304238 case 10:
4239 case 12:
4240 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004241 break;
4242 default:
4243 ret = -EINVAL;
4244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245
4246 switch (sample_rate) {
4247 case 8000:
4248 case 11025:
4249 case 12000:
4250 case 16000:
4251 case 22050:
4252 case 24000:
4253 case 32000:
4254 case 44100:
4255 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004256 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304257 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004258 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304259 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260 break;
4261 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004262 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263 }
4264
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004265 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266}
4267
Naresh Tanniru04f71882018-06-26 17:46:22 +05304268
4269/** Add a value in a list if not already present.
4270 * @return true if value was successfully inserted or already present,
4271 * false if the list is full and does not contain the value.
4272 */
4273static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4274 for (size_t i = 0; i < list_length; i++) {
4275 if (list[i] == value) return true; // value is already present
4276 if (list[i] == 0) { // no values in this slot
4277 list[i] = value;
4278 return true; // value inserted
4279 }
4280 }
4281 return false; // could not insert value
4282}
4283
4284/** Add channel_mask in supported_channel_masks if not already present.
4285 * @return true if channel_mask was successfully inserted or already present,
4286 * false if supported_channel_masks is full and does not contain channel_mask.
4287 */
4288static void register_channel_mask(audio_channel_mask_t channel_mask,
4289 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4290 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4291 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4292}
4293
4294/** Add format in supported_formats if not already present.
4295 * @return true if format was successfully inserted or already present,
4296 * false if supported_formats is full and does not contain format.
4297 */
4298static void register_format(audio_format_t format,
4299 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4300 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4301 "%s: stream can not declare supporting its format %x", __func__, format);
4302}
4303/** Add sample_rate in supported_sample_rates if not already present.
4304 * @return true if sample_rate was successfully inserted or already present,
4305 * false if supported_sample_rates is full and does not contain sample_rate.
4306 */
4307static void register_sample_rate(uint32_t sample_rate,
4308 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4309 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4310 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4311}
4312
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004313static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4314{
4315 uint32_t high = num1, low = num2, temp = 0;
4316
4317 if (!num1 || !num2)
4318 return 0;
4319
4320 if (num1 < num2) {
4321 high = num2;
4322 low = num1;
4323 }
4324
4325 while (low != 0) {
4326 temp = low;
4327 low = high % low;
4328 high = temp;
4329 }
4330 return (num1 * num2)/high;
4331}
4332
4333static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4334{
4335 uint32_t remainder = 0;
4336
4337 if (!multiplier)
4338 return num;
4339
4340 remainder = num % multiplier;
4341 if (remainder)
4342 num += (multiplier - remainder);
4343
4344 return num;
4345}
4346
Aalique Grahame22e49102018-12-18 14:23:57 -08004347static size_t get_stream_buffer_size(size_t duration_ms,
4348 uint32_t sample_rate,
4349 audio_format_t format,
4350 int channel_count,
4351 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352{
4353 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004354 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355
Aalique Grahame22e49102018-12-18 14:23:57 -08004356 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004357 if (is_low_latency)
4358 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304359
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004360 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004361 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362
Ralf Herzbd08d632018-09-28 15:50:49 +02004363 /* make sure the size is multiple of 32 bytes and additionally multiple of
4364 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004365 * At 48 kHz mono 16-bit PCM:
4366 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4367 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004368 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004369 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004370 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004371
4372 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373}
4374
Aalique Grahame22e49102018-12-18 14:23:57 -08004375static size_t get_input_buffer_size(uint32_t sample_rate,
4376 audio_format_t format,
4377 int channel_count,
4378 bool is_low_latency)
4379{
4380 /* Don't know if USB HIFI in this context so use true to be conservative */
4381 if (check_input_parameters(sample_rate, format, channel_count,
4382 true /*is_usb_hifi */) != 0)
4383 return 0;
4384
4385 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4386 sample_rate,
4387 format,
4388 channel_count,
4389 is_low_latency);
4390}
4391
Derek Chenf6318be2017-06-12 17:16:24 -04004392size_t get_output_period_size(uint32_t sample_rate,
4393 audio_format_t format,
4394 int channel_count,
4395 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304396{
4397 size_t size = 0;
4398 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4399
4400 if ((duration == 0) || (sample_rate == 0) ||
4401 (bytes_per_sample == 0) || (channel_count == 0)) {
4402 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4403 bytes_per_sample, channel_count);
4404 return -EINVAL;
4405 }
4406
4407 size = (sample_rate *
4408 duration *
4409 bytes_per_sample *
4410 channel_count) / 1000;
4411 /*
4412 * To have same PCM samples for all channels, the buffer size requires to
4413 * be multiple of (number of channels * bytes per sample)
4414 * For writes to succeed, the buffer must be written at address which is multiple of 32
4415 */
4416 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4417
4418 return (size/(channel_count * bytes_per_sample));
4419}
4420
Zhou Song48453a02018-01-10 17:50:59 +08004421static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304422{
4423 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004424 uint64_t written_frames = 0;
4425 uint64_t kernel_frames = 0;
4426 uint64_t dsp_frames = 0;
4427 uint64_t signed_frames = 0;
4428 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304429
4430 /* This adjustment accounts for buffering after app processor.
4431 * It is based on estimated DSP latency per use case, rather than exact.
4432 */
George Gao9ba8a142020-07-23 14:30:03 -07004433 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004434 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304435
Zhou Song48453a02018-01-10 17:50:59 +08004436 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004437 written_frames = out->written /
4438 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4439
Ashish Jain5106d362016-05-11 19:23:33 +05304440 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4441 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4442 * hence only estimate.
4443 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004444 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4445 kernel_frames = kernel_buffer_size /
4446 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304447
Weiyin Jiang4813da12020-05-28 00:37:28 +08004448 if (written_frames >= (kernel_frames + dsp_frames))
4449 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304450
Zhou Song48453a02018-01-10 17:50:59 +08004451 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304452 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004453 if (timestamp != NULL )
4454 *timestamp = out->writeAt;
4455 } else if (timestamp != NULL) {
4456 clock_gettime(CLOCK_MONOTONIC, timestamp);
4457 }
4458 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304459
Weiyin Jiang4813da12020-05-28 00:37:28 +08004460 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4461 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304462
4463 return actual_frames_rendered;
4464}
4465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4467{
4468 struct stream_out *out = (struct stream_out *)stream;
4469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004470 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471}
4472
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004473static int out_set_sample_rate(struct audio_stream *stream __unused,
4474 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475{
4476 return -ENOSYS;
4477}
4478
4479static size_t out_get_buffer_size(const struct audio_stream *stream)
4480{
4481 struct stream_out *out = (struct stream_out *)stream;
4482
Varun Balaraje49253e2017-07-06 19:48:56 +05304483 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304484 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304485 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304486 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4487 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4488 else
4489 return out->compr_config.fragment_size;
4490 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004491 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304492 else if (is_offload_usecase(out->usecase) &&
4493 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304494 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004495
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004496 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004497 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498}
4499
4500static uint32_t out_get_channels(const struct audio_stream *stream)
4501{
4502 struct stream_out *out = (struct stream_out *)stream;
4503
4504 return out->channel_mask;
4505}
4506
4507static audio_format_t out_get_format(const struct audio_stream *stream)
4508{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004509 struct stream_out *out = (struct stream_out *)stream;
4510
4511 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512}
4513
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004514static int out_set_format(struct audio_stream *stream __unused,
4515 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516{
4517 return -ENOSYS;
4518}
4519
4520static int out_standby(struct audio_stream *stream)
4521{
4522 struct stream_out *out = (struct stream_out *)stream;
4523 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004524 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304526 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4527 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004528
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004529 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004531 if (adev->adm_deregister_stream)
4532 adev->adm_deregister_stream(adev->adm_data, out->handle);
4533
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004534 if (is_offload_usecase(out->usecase)) {
4535 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004536 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004537 pthread_mutex_unlock(&out->latch_lock);
4538 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004539
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004540 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004542 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4543 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304544 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004545 pthread_mutex_unlock(&adev->lock);
4546 pthread_mutex_unlock(&out->lock);
4547 ALOGD("VOIP output entered standby");
4548 return 0;
4549 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004550 if (out->pcm) {
4551 pcm_close(out->pcm);
4552 out->pcm = NULL;
4553 }
Meng Wanga09da002020-04-20 12:56:04 +08004554 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4555 if (adev->haptic_pcm) {
4556 pcm_close(adev->haptic_pcm);
4557 adev->haptic_pcm = NULL;
4558 }
4559
4560 if (adev->haptic_buffer != NULL) {
4561 free(adev->haptic_buffer);
4562 adev->haptic_buffer = NULL;
4563 adev->haptic_buffer_size = 0;
4564 }
4565 adev->haptic_pcm_device_id = 0;
4566 }
4567
Haynes Mathew George16081042017-05-31 17:16:49 -07004568 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4569 do_stop = out->playback_started;
4570 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004571
4572 if (out->mmap_shared_memory_fd >= 0) {
4573 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4574 __func__, out->mmap_shared_memory_fd);
4575 close(out->mmap_shared_memory_fd);
4576 out->mmap_shared_memory_fd = -1;
4577 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004578 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004579 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004580 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304581 out->send_next_track_params = false;
4582 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004583 out->gapless_mdata.encoder_delay = 0;
4584 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004585 if (out->compr != NULL) {
4586 compress_close(out->compr);
4587 out->compr = NULL;
4588 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004589 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004590 if (do_stop) {
4591 stop_output_stream(out);
4592 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304593 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004594 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004595 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 }
4597 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304598 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599 return 0;
4600}
4601
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304602static int out_on_error(struct audio_stream *stream)
4603{
4604 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004605 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304606
4607 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004608 // always send CMD_ERROR for offload streams, this
4609 // is needed e.g. when SSR happens within compress_open
4610 // since the stream is active, offload_callback_thread is also active.
4611 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004612 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004613 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004614 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004615 }
4616 pthread_mutex_unlock(&out->lock);
4617
4618 status = out_standby(&out->stream.common);
4619
4620 lock_output_stream(out);
4621 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004622 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304623 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304624
4625 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4626 ALOGD("Setting previous card status if offline");
4627 out->prev_card_status_offline = true;
4628 }
4629
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304630 pthread_mutex_unlock(&out->lock);
4631
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004632 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304633}
4634
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304635/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004636 * standby implementation without locks, assumes that the callee already
4637 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304638 */
4639int out_standby_l(struct audio_stream *stream)
4640{
4641 struct stream_out *out = (struct stream_out *)stream;
4642 struct audio_device *adev = out->dev;
4643
4644 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4645 stream, out->usecase, use_case_table[out->usecase]);
4646
4647 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004648 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304649 if (adev->adm_deregister_stream)
4650 adev->adm_deregister_stream(adev->adm_data, out->handle);
4651
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004652 if (is_offload_usecase(out->usecase)) {
4653 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304654 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004655 pthread_mutex_unlock(&out->latch_lock);
4656 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304657
4658 out->standby = true;
4659 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4660 voice_extn_compress_voip_close_output_stream(stream);
4661 out->started = 0;
4662 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004663 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304664 return 0;
4665 } else if (!is_offload_usecase(out->usecase)) {
4666 if (out->pcm) {
4667 pcm_close(out->pcm);
4668 out->pcm = NULL;
4669 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004670 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4671 if (adev->haptic_pcm) {
4672 pcm_close(adev->haptic_pcm);
4673 adev->haptic_pcm = NULL;
4674 }
4675
4676 if (adev->haptic_buffer != NULL) {
4677 free(adev->haptic_buffer);
4678 adev->haptic_buffer = NULL;
4679 adev->haptic_buffer_size = 0;
4680 }
4681 adev->haptic_pcm_device_id = 0;
4682 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304683 } else {
4684 ALOGD("copl(%p):standby", out);
4685 out->send_next_track_params = false;
4686 out->is_compr_metadata_avail = false;
4687 out->gapless_mdata.encoder_delay = 0;
4688 out->gapless_mdata.encoder_padding = 0;
4689 if (out->compr != NULL) {
4690 compress_close(out->compr);
4691 out->compr = NULL;
4692 }
4693 }
4694 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004695 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304696 }
4697 ALOGD("%s: exit", __func__);
4698 return 0;
4699}
4700
Aalique Grahame22e49102018-12-18 14:23:57 -08004701static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702{
Aalique Grahame22e49102018-12-18 14:23:57 -08004703 struct stream_out *out = (struct stream_out *)stream;
4704
4705 // We try to get the lock for consistency,
4706 // but it isn't necessary for these variables.
4707 // If we're not in standby, we may be blocked on a write.
4708 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4709 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4710 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4711
Andy Hunga1f48fa2019-07-01 18:14:53 -07004712 char buffer[256]; // for statistics formatting
4713 if (!is_offload_usecase(out->usecase)) {
4714 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4715 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4716 }
4717
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004718 if (out->start_latency_ms.n > 0) {
4719 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4720 dprintf(fd, " Start latency ms: %s\n", buffer);
4721 }
4722
Aalique Grahame22e49102018-12-18 14:23:57 -08004723 if (locked) {
4724 pthread_mutex_unlock(&out->lock);
4725 }
4726
4727 // dump error info
4728 (void)error_log_dump(
4729 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731 return 0;
4732}
4733
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004734static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4735{
4736 int ret = 0;
4737 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004738
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004739 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004740 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004741 return -EINVAL;
4742 }
4743
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304744 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004745
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004746 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4747 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304748 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004749 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004750 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4751 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304752 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004753 }
4754
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004755 ALOGV("%s new encoder delay %u and padding %u", __func__,
4756 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4757
4758 return 0;
4759}
4760
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004761static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4762{
4763 return out == adev->primary_output || out == adev->voice_tx_output;
4764}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004765
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304766// note: this call is safe only if the stream_cb is
4767// removed first in close_output_stream (as is done now).
4768static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4769{
4770 if (!stream || !parms)
4771 return;
4772
4773 struct stream_out *out = (struct stream_out *)stream;
4774 struct audio_device *adev = out->dev;
4775
4776 card_status_t status;
4777 int card;
4778 if (parse_snd_card_status(parms, &card, &status) < 0)
4779 return;
4780
4781 pthread_mutex_lock(&adev->lock);
4782 bool valid_cb = (card == adev->snd_card);
4783 pthread_mutex_unlock(&adev->lock);
4784
4785 if (!valid_cb)
4786 return;
4787
4788 lock_output_stream(out);
4789 if (out->card_status != status)
4790 out->card_status = status;
4791 pthread_mutex_unlock(&out->lock);
4792
4793 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4794 use_case_table[out->usecase],
4795 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4796
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304797 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304798 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304799 if (voice_is_call_state_active(adev) &&
4800 out == adev->primary_output) {
4801 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4802 pthread_mutex_lock(&adev->lock);
4803 voice_stop_call(adev);
4804 adev->mode = AUDIO_MODE_NORMAL;
4805 pthread_mutex_unlock(&adev->lock);
4806 }
4807 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304808 return;
4809}
4810
Kevin Rocardfce19002017-08-07 19:21:36 -07004811static int get_alive_usb_card(struct str_parms* parms) {
4812 int card;
4813 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4814 !audio_extn_usb_alive(card)) {
4815 return card;
4816 }
4817 return -ENODEV;
4818}
4819
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004820int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004821 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004822{
4823 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004824 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004825 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004826 bool bypass_a2dp = false;
4827 bool reconfig = false;
4828 unsigned long service_interval = 0;
4829
4830 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004831 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4832
4833 list_init(&new_devices);
4834 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004835
4836 lock_output_stream(out);
4837 pthread_mutex_lock(&adev->lock);
4838
4839 /*
4840 * When HDMI cable is unplugged the music playback is paused and
4841 * the policy manager sends routing=0. But the audioflinger continues
4842 * to write data until standby time (3sec). As the HDMI core is
4843 * turned off, the write gets blocked.
4844 * Avoid this by routing audio to speaker until standby.
4845 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004846 if (is_single_device_type_equal(&out->device_list,
4847 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004848 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004849 !audio_extn_passthru_is_passthrough_stream(out) &&
4850 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004851 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004852 }
4853 /*
4854 * When A2DP is disconnected the
4855 * music playback is paused and the policy manager sends routing=0
4856 * But the audioflinger continues to write data until standby time
4857 * (3sec). As BT is turned off, the write gets blocked.
4858 * Avoid this by routing audio to speaker until standby.
4859 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004860 if (is_a2dp_out_device_type(&out->device_list) &&
4861 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004862 !audio_extn_a2dp_source_is_ready() &&
4863 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004864 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004865 }
4866 /*
4867 * When USB headset is disconnected the music platback paused
4868 * and the policy manager send routing=0. But if the USB is connected
4869 * back before the standby time, AFE is not closed and opened
4870 * when USB is connected back. So routing to speker will guarantee
4871 * AFE reconfiguration and AFE will be opend once USB is connected again
4872 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004873 if (is_usb_out_device_type(&out->device_list) &&
4874 list_empty(&new_devices) &&
4875 !audio_extn_usb_connected(NULL)) {
4876 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4877 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878 /* To avoid a2dp to sco overlapping / BT device improper state
4879 * check with BT lib about a2dp streaming support before routing
4880 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004881 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004882 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004883 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4884 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004885 //combo usecase just by pass a2dp
4886 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4887 bypass_a2dp = true;
4888 } else {
4889 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4890 /* update device to a2dp and don't route as BT returned error
4891 * However it is still possible a2dp routing called because
4892 * of current active device disconnection (like wired headset)
4893 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004894 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004895 pthread_mutex_unlock(&adev->lock);
4896 pthread_mutex_unlock(&out->lock);
4897 goto error;
4898 }
4899 }
4900 }
4901
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004902 // Workaround: If routing to an non existing usb device, fail gracefully
4903 // The routing request will otherwise block during 10 second
4904 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 if (is_usb_out_device_type(&new_devices)) {
4906 struct str_parms *parms =
4907 str_parms_create_str(get_usb_device_address(&new_devices));
4908 if (!parms)
4909 goto error;
4910 if ((card = get_alive_usb_card(parms)) >= 0) {
4911 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4912 pthread_mutex_unlock(&adev->lock);
4913 pthread_mutex_unlock(&out->lock);
4914 str_parms_destroy(parms);
4915 ret = -ENOSYS;
4916 goto error;
4917 }
4918 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004919 }
4920
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004921 // Workaround: If routing to an non existing hdmi device, fail gracefully
4922 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4923 (platform_get_edid_info_v2(adev->platform,
4924 out->extconn.cs.controller,
4925 out->extconn.cs.stream) != 0)) {
4926 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4927 pthread_mutex_unlock(&adev->lock);
4928 pthread_mutex_unlock(&out->lock);
4929 ret = -ENOSYS;
4930 goto error;
4931 }
4932
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004933 /*
4934 * select_devices() call below switches all the usecases on the same
4935 * backend to the new device. Refer to check_usecases_codec_backend() in
4936 * the select_devices(). But how do we undo this?
4937 *
4938 * For example, music playback is active on headset (deep-buffer usecase)
4939 * and if we go to ringtones and select a ringtone, low-latency usecase
4940 * will be started on headset+speaker. As we can't enable headset+speaker
4941 * and headset devices at the same time, select_devices() switches the music
4942 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4943 * So when the ringtone playback is completed, how do we undo the same?
4944 *
4945 * We are relying on the out_set_parameters() call on deep-buffer output,
4946 * once the ringtone playback is ended.
4947 * NOTE: We should not check if the current devices are same as new devices.
4948 * Because select_devices() must be called to switch back the music
4949 * playback to headset.
4950 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004951 if (!list_empty(&new_devices)) {
4952 bool same_dev = compare_devices(&out->device_list, &new_devices);
4953 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004954
4955 if (output_drives_call(adev, out)) {
4956 if (!voice_is_call_state_active(adev)) {
4957 if (adev->mode == AUDIO_MODE_IN_CALL) {
4958 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004959 ret = voice_start_call(adev);
4960 }
4961 } else {
4962 adev->current_call_output = out;
4963 voice_update_devices_for_all_voice_usecases(adev);
4964 }
4965 }
4966
Mingshu Pang60536d72020-09-09 15:28:22 +08004967 if (is_usb_out_device_type(&out->device_list)) {
4968 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4969 audio_extn_usb_set_service_interval(true /*playback*/,
4970 service_interval,
4971 &reconfig);
4972 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4973 }
4974
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004975 if (!out->standby) {
4976 if (!same_dev) {
4977 ALOGV("update routing change");
4978 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4979 adev->perf_lock_opts,
4980 adev->perf_lock_opts_size);
4981 if (adev->adm_on_routing_change)
4982 adev->adm_on_routing_change(adev->adm_data,
4983 out->handle);
4984 }
4985 if (!bypass_a2dp) {
4986 select_devices(adev, out->usecase);
4987 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004988 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4989 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004991 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004992 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004993 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004994 }
4995
4996 if (!same_dev) {
4997 // on device switch force swap, lower functions will make sure
4998 // to check if swap is allowed or not.
4999 platform_set_swap_channels(adev, true);
5000 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5001 }
5002 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005003 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005004 pthread_mutex_lock(&out->latch_lock);
5005 if (out->a2dp_compress_mute) {
5006 out->a2dp_compress_mute = false;
5007 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5008 }
5009 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005010 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5011 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5012 }
5013 }
5014 }
5015
5016 pthread_mutex_unlock(&adev->lock);
5017 pthread_mutex_unlock(&out->lock);
5018
5019 /*handles device and call state changes*/
5020 audio_extn_extspk_update(adev->extspk);
5021
5022error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005023 ALOGV("%s: exit: code(%d)", __func__, ret);
5024 return ret;
5025}
5026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5028{
5029 struct stream_out *out = (struct stream_out *)stream;
5030 struct audio_device *adev = out->dev;
5031 struct str_parms *parms;
5032 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005033 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005034 int ext_controller = -1;
5035 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036
sangwoobc677242013-08-08 16:53:43 +09005037 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005038 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305040 if (!parms)
5041 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005042
5043 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5044 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005045 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005046 out->extconn.cs.controller = ext_controller;
5047 out->extconn.cs.stream = ext_stream;
5048 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5049 use_case_table[out->usecase], out->extconn.cs.controller,
5050 out->extconn.cs.stream);
5051 }
5052
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005053 if (out == adev->primary_output) {
5054 pthread_mutex_lock(&adev->lock);
5055 audio_extn_set_parameters(adev, parms);
5056 pthread_mutex_unlock(&adev->lock);
5057 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005058 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005059 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005060 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005061
5062 audio_extn_dts_create_state_notifier_node(out->usecase);
5063 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5064 popcount(out->channel_mask),
5065 out->playback_started);
5066
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005067 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005068 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005069
Surendar Karkaf51b5842018-04-26 11:28:38 +05305070 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5071 sizeof(value));
5072 if (err >= 0) {
5073 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5074 audio_extn_send_dual_mono_mixing_coefficients(out);
5075 }
5076
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305077 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5078 if (err >= 0) {
5079 strlcpy(out->profile, value, sizeof(out->profile));
5080 ALOGV("updating stream profile with value '%s'", out->profile);
5081 lock_output_stream(out);
5082 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5083 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005084 &out->device_list, out->flags,
5085 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305086 out->sample_rate, out->bit_width,
5087 out->channel_mask, out->profile,
5088 &out->app_type_cfg);
5089 pthread_mutex_unlock(&out->lock);
5090 }
5091
Alexy Joseph98988832017-01-13 14:56:59 -08005092 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005093 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5094 // and vendor.audio.hal.output.suspend.supported is set to true
5095 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005096 //check suspend parameter only for low latency and if the property
5097 //is enabled
5098 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5099 ALOGI("%s: got suspend_playback %s", __func__, value);
5100 lock_output_stream(out);
5101 if (!strncmp(value, "false", 5)) {
5102 //suspend_playback=false is supposed to set QOS value back to 75%
5103 //the mixer control sent with value Enable will achieve that
5104 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5105 } else if (!strncmp (value, "true", 4)) {
5106 //suspend_playback=true is supposed to remove QOS value
5107 //resetting the mixer control will set the default value
5108 //for the mixer control which is Disable and this removes the QOS vote
5109 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5110 } else {
5111 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5112 " got %s", __func__, value);
5113 ret = -1;
5114 }
5115
5116 if (ret != 0) {
5117 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5118 __func__, out->pm_qos_mixer_path, ret);
5119 }
5120
5121 pthread_mutex_unlock(&out->lock);
5122 }
5123 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005124
Alexy Joseph98988832017-01-13 14:56:59 -08005125 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305127error:
Eric Laurent994a6932013-07-17 11:51:42 -07005128 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 return ret;
5130}
5131
Paul McLeana50b7332018-12-17 08:24:21 -07005132static int in_set_microphone_direction(const struct audio_stream_in *stream,
5133 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005134 struct stream_in *in = (struct stream_in *)stream;
5135
5136 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5137
5138 in->direction = dir;
5139
5140 if (in->standby)
5141 return 0;
5142
5143 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005144}
5145
5146static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005147 struct stream_in *in = (struct stream_in *)stream;
5148
5149 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5150
5151 if (zoom > 1.0 || zoom < -1.0)
5152 return -EINVAL;
5153
5154 in->zoom = zoom;
5155
5156 if (in->standby)
5157 return 0;
5158
5159 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005160}
5161
5162
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005163static bool stream_get_parameter_channels(struct str_parms *query,
5164 struct str_parms *reply,
5165 audio_channel_mask_t *supported_channel_masks) {
5166 int ret = -1;
5167 char value[512];
5168 bool first = true;
5169 size_t i, j;
5170
5171 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5172 ret = 0;
5173 value[0] = '\0';
5174 i = 0;
5175 while (supported_channel_masks[i] != 0) {
5176 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5177 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5178 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305179 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005180
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305181 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005182 first = false;
5183 break;
5184 }
5185 }
5186 i++;
5187 }
5188 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5189 }
5190 return ret == 0;
5191}
5192
5193static bool stream_get_parameter_formats(struct str_parms *query,
5194 struct str_parms *reply,
5195 audio_format_t *supported_formats) {
5196 int ret = -1;
5197 char value[256];
5198 size_t i, j;
5199 bool first = true;
5200
5201 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5202 ret = 0;
5203 value[0] = '\0';
5204 i = 0;
5205 while (supported_formats[i] != 0) {
5206 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5207 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5208 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305209 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005210 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305211 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005212 first = false;
5213 break;
5214 }
5215 }
5216 i++;
5217 }
5218 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5219 }
5220 return ret == 0;
5221}
5222
5223static bool stream_get_parameter_rates(struct str_parms *query,
5224 struct str_parms *reply,
5225 uint32_t *supported_sample_rates) {
5226
5227 int i;
5228 char value[256];
5229 int ret = -1;
5230 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5231 ret = 0;
5232 value[0] = '\0';
5233 i=0;
5234 int cursor = 0;
5235 while (supported_sample_rates[i]) {
5236 int avail = sizeof(value) - cursor;
5237 ret = snprintf(value + cursor, avail, "%s%d",
5238 cursor > 0 ? "|" : "",
5239 supported_sample_rates[i]);
5240 if (ret < 0 || ret >= avail) {
5241 // if cursor is at the last element of the array
5242 // overwrite with \0 is duplicate work as
5243 // snprintf already put a \0 in place.
5244 // else
5245 // we had space to write the '|' at value[cursor]
5246 // (which will be overwritten) or no space to fill
5247 // the first element (=> cursor == 0)
5248 value[cursor] = '\0';
5249 break;
5250 }
5251 cursor += ret;
5252 ++i;
5253 }
5254 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5255 value);
5256 }
5257 return ret >= 0;
5258}
5259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5261{
5262 struct stream_out *out = (struct stream_out *)stream;
5263 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005264 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265 char value[256];
5266 struct str_parms *reply = str_parms_create();
5267 size_t i, j;
5268 int ret;
5269 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005270
5271 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005272 if (reply) {
5273 str_parms_destroy(reply);
5274 }
5275 if (query) {
5276 str_parms_destroy(query);
5277 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005278 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5279 return NULL;
5280 }
5281
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005282 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005283 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5284 if (ret >= 0) {
5285 value[0] = '\0';
5286 i = 0;
5287 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005288 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5289 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005291 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005293 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005294 first = false;
5295 break;
5296 }
5297 }
5298 i++;
5299 }
5300 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5301 str = str_parms_to_str(reply);
5302 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005303 voice_extn_out_get_parameters(out, query, reply);
5304 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005305 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005306
Alexy Joseph62142aa2015-11-16 15:10:34 -08005307
5308 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5309 if (ret >= 0) {
5310 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305311 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5312 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005313 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305314 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005315 } else {
5316 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305317 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005318 }
5319 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005320 if (str)
5321 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005322 str = str_parms_to_str(reply);
5323 }
5324
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005325 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5326 if (ret >= 0) {
5327 value[0] = '\0';
5328 i = 0;
5329 first = true;
5330 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005331 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5332 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005333 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005334 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005335 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005336 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005337 first = false;
5338 break;
5339 }
5340 }
5341 i++;
5342 }
5343 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005344 if (str)
5345 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005346 str = str_parms_to_str(reply);
5347 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005348
5349 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5350 if (ret >= 0) {
5351 value[0] = '\0';
5352 i = 0;
5353 first = true;
5354 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005355 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5356 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005357 if (!first) {
5358 strlcat(value, "|", sizeof(value));
5359 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005360 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005361 first = false;
5362 break;
5363 }
5364 }
5365 i++;
5366 }
5367 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5368 if (str)
5369 free(str);
5370 str = str_parms_to_str(reply);
5371 }
5372
Alexy Joseph98988832017-01-13 14:56:59 -08005373 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5374 //only low latency track supports suspend_resume
5375 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005376 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005377 if (str)
5378 free(str);
5379 str = str_parms_to_str(reply);
5380 }
5381
5382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005383 str_parms_destroy(query);
5384 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005385 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005386 return str;
5387}
5388
5389static uint32_t out_get_latency(const struct audio_stream_out *stream)
5390{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005391 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005392 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005393 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005394
Alexy Josephaa54c872014-12-03 02:46:47 -08005395 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305396 lock_output_stream(out);
5397 latency = audio_extn_utils_compress_get_dsp_latency(out);
5398 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005399 } else if ((out->realtime) ||
5400 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005401 // since the buffer won't be filled up faster than realtime,
5402 // return a smaller number
5403 if (out->config.rate)
5404 period_ms = (out->af_period_multiplier * out->config.period_size *
5405 1000) / (out->config.rate);
5406 else
5407 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005408 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005409 } else {
5410 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005411 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005412 }
5413
Zhou Songd2537a02020-06-11 22:04:46 +08005414 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005415 latency += audio_extn_a2dp_get_encoder_latency();
5416
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305417 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005418 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005419}
5420
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305421static float AmpToDb(float amplification)
5422{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305423 float db = DSD_VOLUME_MIN_DB;
5424 if (amplification > 0) {
5425 db = 20 * log10(amplification);
5426 if(db < DSD_VOLUME_MIN_DB)
5427 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305428 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305429 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305430}
5431
Arun Mirpuri5d170872019-03-26 13:21:31 -07005432static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5433 float right)
5434{
5435 struct stream_out *out = (struct stream_out *)stream;
5436 long volume = 0;
5437 char mixer_ctl_name[128] = "";
5438 struct audio_device *adev = out->dev;
5439 struct mixer_ctl *ctl = NULL;
5440 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5441 PCM_PLAYBACK);
5442
5443 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5444 "Playback %d Volume", pcm_device_id);
5445 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5446 if (!ctl) {
5447 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5448 __func__, mixer_ctl_name);
5449 return -EINVAL;
5450 }
5451 if (left != right)
5452 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5453 __func__, left, right);
5454 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5455 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5456 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5457 __func__, mixer_ctl_name, volume);
5458 return -EINVAL;
5459 }
5460 return 0;
5461}
5462
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305463static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5464 float right)
5465{
5466 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305467 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305468 char mixer_ctl_name[128];
5469 struct audio_device *adev = out->dev;
5470 struct mixer_ctl *ctl;
5471 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5472 PCM_PLAYBACK);
5473
5474 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5475 "Compress Playback %d Volume", pcm_device_id);
5476 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5477 if (!ctl) {
5478 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5479 __func__, mixer_ctl_name);
5480 return -EINVAL;
5481 }
5482 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5483 __func__, mixer_ctl_name, left, right);
5484 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5485 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5486 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5487
5488 return 0;
5489}
5490
Zhou Song2b8f28f2017-09-11 10:51:38 +08005491static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5492 float right)
5493{
5494 struct stream_out *out = (struct stream_out *)stream;
5495 char mixer_ctl_name[] = "App Type Gain";
5496 struct audio_device *adev = out->dev;
5497 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305498 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005499
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005500 if (!is_valid_volume(left, right)) {
5501 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5502 __func__, left, right);
5503 return -EINVAL;
5504 }
5505
Zhou Song2b8f28f2017-09-11 10:51:38 +08005506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5507 if (!ctl) {
5508 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5509 __func__, mixer_ctl_name);
5510 return -EINVAL;
5511 }
5512
5513 set_values[0] = 0; //0: Rx Session 1:Tx Session
5514 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305515 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5516 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005517
5518 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5519 return 0;
5520}
5521
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305522static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5523 float right)
5524{
5525 struct stream_out *out = (struct stream_out *)stream;
5526 /* Volume control for pcm playback */
5527 if (left != right) {
5528 return -EINVAL;
5529 } else {
5530 char mixer_ctl_name[128];
5531 struct audio_device *adev = out->dev;
5532 struct mixer_ctl *ctl;
5533 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5534 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5535 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5536 if (!ctl) {
5537 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5538 return -EINVAL;
5539 }
5540
5541 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5542 int ret = mixer_ctl_set_value(ctl, 0, volume);
5543 if (ret < 0) {
5544 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5545 return -EINVAL;
5546 }
5547
5548 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5549
5550 return 0;
5551 }
5552}
5553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554static int out_set_volume(struct audio_stream_out *stream, float left,
5555 float right)
5556{
Eric Laurenta9024de2013-04-04 09:19:12 -07005557 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005558 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305559 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005560
Arun Mirpuri5d170872019-03-26 13:21:31 -07005561 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005562 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5563 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005564 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005565 out->muted = (left == 0.0f);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005566 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005567 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005568 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305569 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005570 /*
5571 * Set mute or umute on HDMI passthrough stream.
5572 * Only take left channel into account.
5573 * Mute is 0 and unmute 1
5574 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305575 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305576 } else if (out->format == AUDIO_FORMAT_DSD){
5577 char mixer_ctl_name[128] = "DSD Volume";
5578 struct audio_device *adev = out->dev;
5579 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5580
5581 if (!ctl) {
5582 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5583 __func__, mixer_ctl_name);
5584 return -EINVAL;
5585 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305586 volume[0] = (long)(AmpToDb(left));
5587 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305588 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5589 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005590 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005591 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005592 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5593 struct listnode *node = NULL;
5594 list_for_each(node, &adev->active_outputs_list) {
5595 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5596 streams_output_ctxt_t,
5597 list);
5598 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5599 out->volume_l = out_ctxt->output->volume_l;
5600 out->volume_r = out_ctxt->output->volume_r;
5601 }
5602 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005603 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005604 if (!out->a2dp_compress_mute) {
5605 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5606 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005607 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005608 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005609 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005610 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005611 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305612 if (!out->a2dp_compress_mute)
5613 ret = out_set_compr_volume(stream, left, right);
5614 out->volume_l = left;
5615 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005616 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305617 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005618 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005619 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005620 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5621 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5622 if (!out->standby) {
5623 audio_extn_utils_send_app_type_gain(out->dev,
5624 out->app_type_cfg.app_type,
5625 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005626 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005627 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005628 out->volume_l = left;
5629 out->volume_r = right;
5630 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005631 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5632 ALOGV("%s: MMAP set volume called", __func__);
5633 if (!out->standby)
5634 ret = out_set_mmap_volume(stream, left, right);
5635 out->volume_l = left;
5636 out->volume_r = right;
5637 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305638 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305639 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5640 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305641 /* Volume control for pcm playback */
5642 if (!out->standby)
5643 ret = out_set_pcm_volume(stream, left, right);
5644 else
5645 out->apply_volume = true;
5646
5647 out->volume_l = left;
5648 out->volume_r = right;
5649 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005650 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5651 ALOGV("%s: bus device set volume called", __func__);
5652 if (!out->standby)
5653 ret = out_set_pcm_volume(stream, left, right);
5654 out->volume_l = left;
5655 out->volume_r = right;
5656 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005657 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005659 return -ENOSYS;
5660}
5661
Zhou Songc9672822017-08-16 16:01:39 +08005662static void update_frames_written(struct stream_out *out, size_t bytes)
5663{
5664 size_t bpf = 0;
5665
5666 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5667 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5668 bpf = 1;
5669 else if (!is_offload_usecase(out->usecase))
5670 bpf = audio_bytes_per_sample(out->format) *
5671 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005672
5673 pthread_mutex_lock(&out->position_query_lock);
5674 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005675 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005676 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5677 }
5678 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005679}
5680
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005681int split_and_write_audio_haptic_data(struct stream_out *out,
5682 const void *buffer, size_t bytes_to_write)
5683{
5684 struct audio_device *adev = out->dev;
5685
5686 int ret = 0;
5687 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5688 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5689 size_t frame_size = channel_count * bytes_per_sample;
5690 size_t frame_count = bytes_to_write / frame_size;
5691
5692 bool force_haptic_path =
5693 property_get_bool("vendor.audio.test_haptic", false);
5694
5695 // extract Haptics data from Audio buffer
5696 bool alloc_haptic_buffer = false;
5697 int haptic_channel_count = adev->haptics_config.channels;
5698 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5699 size_t audio_frame_size = frame_size - haptic_frame_size;
5700 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5701
5702 if (adev->haptic_buffer == NULL) {
5703 alloc_haptic_buffer = true;
5704 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5705 free(adev->haptic_buffer);
5706 adev->haptic_buffer_size = 0;
5707 alloc_haptic_buffer = true;
5708 }
5709
5710 if (alloc_haptic_buffer) {
5711 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005712 if(adev->haptic_buffer == NULL) {
5713 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5714 return -ENOMEM;
5715 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005716 adev->haptic_buffer_size = total_haptic_buffer_size;
5717 }
5718
5719 size_t src_index = 0, aud_index = 0, hap_index = 0;
5720 uint8_t *audio_buffer = (uint8_t *)buffer;
5721 uint8_t *haptic_buffer = adev->haptic_buffer;
5722
5723 // This is required for testing only. This works for stereo data only.
5724 // One channel is fed to audio stream and other to haptic stream for testing.
5725 if (force_haptic_path)
5726 audio_frame_size = haptic_frame_size = bytes_per_sample;
5727
5728 for (size_t i = 0; i < frame_count; i++) {
5729 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5730 audio_frame_size);
5731 aud_index += audio_frame_size;
5732 src_index += audio_frame_size;
5733
5734 if (adev->haptic_pcm)
5735 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5736 haptic_frame_size);
5737 hap_index += haptic_frame_size;
5738 src_index += haptic_frame_size;
5739
5740 // This is required for testing only.
5741 // Discard haptic channel data.
5742 if (force_haptic_path)
5743 src_index += haptic_frame_size;
5744 }
5745
5746 // write to audio pipeline
5747 ret = pcm_write(out->pcm, (void *)audio_buffer,
5748 frame_count * audio_frame_size);
5749
5750 // write to haptics pipeline
5751 if (adev->haptic_pcm)
5752 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5753 frame_count * haptic_frame_size);
5754
5755 return ret;
5756}
5757
Aalique Grahame22e49102018-12-18 14:23:57 -08005758#ifdef NO_AUDIO_OUT
5759static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5760 const void *buffer __unused, size_t bytes)
5761{
5762 struct stream_out *out = (struct stream_out *)stream;
5763
5764 /* No Output device supported other than BT for playback.
5765 * Sleep for the amount of buffer duration
5766 */
5767 lock_output_stream(out);
5768 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5769 (const struct audio_stream_out *)&out->stream) /
5770 out_get_sample_rate(&out->stream.common));
5771 pthread_mutex_unlock(&out->lock);
5772 return bytes;
5773}
5774#endif
5775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5777 size_t bytes)
5778{
5779 struct stream_out *out = (struct stream_out *)stream;
5780 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005781 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305782 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005783 const size_t frame_size = audio_stream_out_frame_size(stream);
5784 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305785 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005786 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005787
Haynes Mathew George380745d2017-10-04 15:27:45 -07005788 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005789 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305790
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305791 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005792
Dhananjay Kumarac341582017-02-23 23:42:25 +05305793 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305794 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305795 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5796 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005797 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305798 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305799 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305800 ALOGD(" %s: sound card is not active/SSR state", __func__);
5801 ret= -EIO;
5802 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305803 }
5804 }
5805
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305806 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305807 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305808 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305809 goto exit;
5810 }
5811
Haynes Mathew George16081042017-05-31 17:16:49 -07005812 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5813 ret = -EINVAL;
5814 goto exit;
5815 }
5816
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005817 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305818 !out->is_iec61937_info_available) {
5819
5820 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5821 out->is_iec61937_info_available = true;
5822 } else if (audio_extn_passthru_is_enabled()) {
5823 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305824 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305825
5826 if((out->format == AUDIO_FORMAT_DTS) ||
5827 (out->format == AUDIO_FORMAT_DTS_HD)) {
5828 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5829 buffer, bytes);
5830 if (ret) {
5831 if (ret != -ENOSYS) {
5832 out->is_iec61937_info_available = false;
5833 ALOGD("iec61937 transmission info not yet updated retry");
5834 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305835 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305836 /* if stream has started and after that there is
5837 * stream config change (iec transmission config)
5838 * then trigger select_device to update backend configuration.
5839 */
5840 out->stream_config_changed = true;
5841 pthread_mutex_lock(&adev->lock);
5842 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305843 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005844 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305845 ret = -EINVAL;
5846 goto exit;
5847 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305848 pthread_mutex_unlock(&adev->lock);
5849 out->stream_config_changed = false;
5850 out->is_iec61937_info_available = true;
5851 }
5852 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305853
Meng Wang4c32fb42020-01-16 17:57:11 +08005854#ifdef AUDIO_GKI_ENABLED
5855 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5856 compr_passthr = out->compr_config.codec->reserved[0];
5857#else
5858 compr_passthr = out->compr_config.codec->compr_passthr;
5859#endif
5860
Garmond Leung317cbf12017-09-13 16:20:50 -07005861 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005862 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305863 (out->is_iec61937_info_available == true)) {
5864 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5865 ret = -EINVAL;
5866 goto exit;
5867 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305868 }
5869 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305870
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005871 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005872 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005873 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5874 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305875 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305876 ret = -EIO;
5877 goto exit;
5878 }
5879 }
5880 }
5881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005882 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005883 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005884 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5885
Eric Laurent150dbfe2013-02-27 14:31:02 -08005886 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005887 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5888 ret = voice_extn_compress_voip_start_output_stream(out);
5889 else
5890 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005891 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005892 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005893 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005894 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005895 goto exit;
5896 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305897 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005898 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005899
5900 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005901 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005902 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305903 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005904 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005905 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305906
5907 if ((out->is_iec61937_info_available == true) &&
5908 (audio_extn_passthru_is_passthrough_stream(out))&&
5909 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5910 ret = -EINVAL;
5911 goto exit;
5912 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305913 if (out->set_dual_mono)
5914 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005915
5916 // log startup time in ms.
5917 simple_stats_log(
5918 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005919 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005920
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005921 if (adev->is_channel_status_set == false &&
5922 compare_device_type(&out->device_list,
5923 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005924 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305925 adev->is_channel_status_set = true;
5926 }
5927
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305928 if ((adev->use_old_pspd_mix_ctrl == true) &&
5929 (out->pspd_coeff_sent == false)) {
5930 /*
5931 * Need to resend pspd coefficients after stream started for
5932 * older kernel version as it does not save the coefficients
5933 * and also stream has to be started for coeff to apply.
5934 */
5935 usecase = get_usecase_from_list(adev, out->usecase);
5936 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305937 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305938 out->pspd_coeff_sent = true;
5939 }
5940 }
5941
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005942 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005943 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005944 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005945 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005946 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5947 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305948 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5949 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005950 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305951 out->send_next_track_params = false;
5952 out->is_compr_metadata_avail = false;
5953 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005954 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305955 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305956 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005957
Ashish Jain83a6cc22016-06-28 14:34:17 +05305958 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305959 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305960 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305961 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005962 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305963 return -EINVAL;
5964 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305965 audio_format_t dst_format = out->hal_op_format;
5966 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305967
Dieter Luecking5d57def2018-09-07 14:23:37 +02005968 /* prevent division-by-zero */
5969 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5970 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5971 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5972 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305973 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005974 ATRACE_END();
5975 return -EINVAL;
5976 }
5977
Ashish Jainf1eaa582016-05-23 20:54:24 +05305978 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5979 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5980
Ashish Jain83a6cc22016-06-28 14:34:17 +05305981 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305982 dst_format,
5983 buffer,
5984 src_format,
5985 frames);
5986
Ashish Jain83a6cc22016-06-28 14:34:17 +05305987 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305988 bytes_to_write);
5989
5990 /*Convert written bytes in audio flinger format*/
5991 if (ret > 0)
5992 ret = ((ret * format_to_bitwidth_table[out->format]) /
5993 format_to_bitwidth_table[dst_format]);
5994 }
5995 } else
5996 ret = compress_write(out->compr, buffer, bytes);
5997
Zhou Songc9672822017-08-16 16:01:39 +08005998 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5999 update_frames_written(out, bytes);
6000
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306001 if (ret < 0)
6002 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006003 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306004 /*msg to cb thread only if non blocking write is enabled*/
6005 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306006 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006007 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306008 } else if (-ENETRESET == ret) {
6009 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306010 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306011 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306012 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006013 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306014 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 }
Ashish Jain5106d362016-05-11 19:23:33 +05306016
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306017 /* Call compr start only when non-zero bytes of data is there to be rendered */
6018 if (!out->playback_started && ret > 0) {
6019 int status = compress_start(out->compr);
6020 if (status < 0) {
6021 ret = status;
6022 ALOGE("%s: compr start failed with err %d", __func__, errno);
6023 goto exit;
6024 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006025 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006026 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006027 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006028 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006029 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006030
6031 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6032 popcount(out->channel_mask),
6033 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006034 }
6035 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006036 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006037 return ret;
6038 } else {
6039 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006040 size_t bytes_to_write = bytes;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006041 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 if (out->muted)
6043 memset((void *)buffer, 0, bytes);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006044 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006045 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6046 __func__, frames, frame_size, bytes_to_write);
6047
Aalique Grahame22e49102018-12-18 14:23:57 -08006048 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006049 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6050 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6051 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006052 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6053 int16_t *src = (int16_t *)buffer;
6054 int16_t *dst = (int16_t *)buffer;
6055
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006056 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006057 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006058 "out_write called for %s use case with wrong properties",
6059 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006060
6061 /*
6062 * FIXME: this can be removed once audio flinger mixer supports
6063 * mono output
6064 */
6065
6066 /*
6067 * Code below goes over each frame in the buffer and adds both
6068 * L and R samples and then divides by 2 to convert to mono
6069 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006070 if (channel_count == 2) {
6071 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6072 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6073 }
6074 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006075 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006076 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006077
6078 // Note: since out_get_presentation_position() is called alternating with out_write()
6079 // by AudioFlinger, we can check underruns using the prior timestamp read.
6080 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6081 if (out->last_fifo_valid) {
6082 // compute drain to see if there is an underrun.
6083 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306084 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6085 int64_t frames_by_time =
6086 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6087 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006088 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6089
6090 if (underrun > 0) {
6091 simple_stats_log(&out->fifo_underruns, underrun);
6092
6093 ALOGW("%s: underrun(%lld) "
6094 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6095 __func__,
6096 (long long)out->fifo_underruns.n,
6097 (long long)frames_by_time,
6098 (long long)out->last_fifo_frames_remaining);
6099 }
6100 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6101 }
6102
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306103 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006104
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006105 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006106
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006107 if (out->config.rate)
6108 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6109 out->config.rate;
6110
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006111 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006112 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6113
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006114 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006115 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006116 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306117 out->convert_buffer != NULL) {
6118
6119 memcpy_by_audio_format(out->convert_buffer,
6120 out->hal_op_format,
6121 buffer,
6122 out->hal_ip_format,
6123 out->config.period_size * out->config.channels);
6124
6125 ret = pcm_write(out->pcm, out->convert_buffer,
6126 (out->config.period_size *
6127 out->config.channels *
6128 format_to_bitwidth_table[out->hal_op_format]));
6129 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306130 /*
6131 * To avoid underrun in DSP when the application is not pumping
6132 * data at required rate, check for the no. of bytes and ignore
6133 * pcm_write if it is less than actual buffer size.
6134 * It is a work around to a change in compress VOIP driver.
6135 */
6136 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6137 bytes < (out->config.period_size * out->config.channels *
6138 audio_bytes_per_sample(out->format))) {
6139 size_t voip_buf_size =
6140 out->config.period_size * out->config.channels *
6141 audio_bytes_per_sample(out->format);
6142 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6143 __func__, bytes, voip_buf_size);
6144 usleep(((uint64_t)voip_buf_size - bytes) *
6145 1000000 / audio_stream_out_frame_size(stream) /
6146 out_get_sample_rate(&out->stream.common));
6147 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006148 } else {
6149 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6150 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6151 else
6152 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6153 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306154 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006155
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006156 release_out_focus(out);
6157
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306158 if (ret < 0)
6159 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006160 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306161 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006163 }
6164
6165exit:
Zhou Songc9672822017-08-16 16:01:39 +08006166 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306167 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306168 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006170 pthread_mutex_unlock(&out->lock);
6171
6172 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006173 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006174 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306175 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306176 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306177 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306178 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306179 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306180 out->standby = true;
6181 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306182 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006183 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6184 /* prevent division-by-zero */
6185 uint32_t stream_size = audio_stream_out_frame_size(stream);
6186 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006187
Dieter Luecking5d57def2018-09-07 14:23:37 +02006188 if ((stream_size == 0) || (srate == 0)) {
6189 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6190 ATRACE_END();
6191 return -EINVAL;
6192 }
6193 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6194 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006195 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306196 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006197 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006198 return ret;
6199 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006201 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006202 return bytes;
6203}
6204
6205static int out_get_render_position(const struct audio_stream_out *stream,
6206 uint32_t *dsp_frames)
6207{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006208 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006209
6210 if (dsp_frames == NULL)
6211 return -EINVAL;
6212
6213 *dsp_frames = 0;
6214 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006215 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306216
6217 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6218 * this operation and adev_close_output_stream(where out gets reset).
6219 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306220 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006221 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306222 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006223 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306224 return 0;
6225 }
6226
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006227 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306228 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306229 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006230 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306231 if (ret < 0)
6232 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006233 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306234 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006235 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306236 if (-ENETRESET == ret) {
6237 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306238 out->card_status = CARD_STATUS_OFFLINE;
6239 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306240 } else if(ret < 0) {
6241 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306242 ret = -EINVAL;
6243 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306244 /*
6245 * Handle corner case where compress session is closed during SSR
6246 * and timestamp is queried
6247 */
6248 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306249 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306250 } else if (out->prev_card_status_offline) {
6251 ALOGE("ERROR: previously sound card was offline,return error");
6252 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306253 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306254 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006255 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306256 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306257 pthread_mutex_unlock(&out->lock);
6258 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006259 } else if (audio_is_linear_pcm(out->format)) {
6260 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006261 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006262 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006263 } else
6264 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006265}
6266
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006267static int out_add_audio_effect(const struct audio_stream *stream __unused,
6268 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006269{
6270 return 0;
6271}
6272
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006273static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6274 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006275{
6276 return 0;
6277}
6278
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006279static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6280 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006281{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306282 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006283}
6284
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006285static int out_get_presentation_position(const struct audio_stream_out *stream,
6286 uint64_t *frames, struct timespec *timestamp)
6287{
6288 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306289 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006290 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006291
Ashish Jain5106d362016-05-11 19:23:33 +05306292 /* below piece of code is not guarded against any lock because audioFliner serializes
6293 * this operation and adev_close_output_stream( where out gets reset).
6294 */
6295 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306296 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006297 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306298 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6299 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6300 return 0;
6301 }
6302
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006303 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006304
Ashish Jain5106d362016-05-11 19:23:33 +05306305 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6306 ret = compress_get_tstamp(out->compr, &dsp_frames,
6307 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006308 // Adjustment accounts for A2dp encoder latency with offload usecases
6309 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006310 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006311 unsigned long offset =
6312 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6313 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6314 }
Ashish Jain5106d362016-05-11 19:23:33 +05306315 ALOGVV("%s rendered frames %ld sample_rate %d",
6316 __func__, dsp_frames, out->sample_rate);
6317 *frames = dsp_frames;
6318 if (ret < 0)
6319 ret = -errno;
6320 if (-ENETRESET == ret) {
6321 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306322 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306323 ret = -EINVAL;
6324 } else
6325 ret = 0;
6326 /* this is the best we can do */
6327 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006328 } else {
6329 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006330 unsigned int avail;
6331 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006332 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006333 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006334
Andy Hunga1f48fa2019-07-01 18:14:53 -07006335 if (out->kernel_buffer_size > avail) {
6336 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6337 } else {
6338 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6339 __func__, avail, out->kernel_buffer_size);
6340 avail = out->kernel_buffer_size;
6341 frames_temp = out->last_fifo_frames_remaining = 0;
6342 }
6343 out->last_fifo_valid = true;
6344 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6345
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006346 if (out->written >= frames_temp)
6347 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006348
Andy Hunga1f48fa2019-07-01 18:14:53 -07006349 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6350 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6351
Weiyin Jiangd4633762018-03-16 12:05:03 +08006352 // This adjustment accounts for buffering after app processor.
6353 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006354 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006355 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006356 if (signed_frames >= frames_temp)
6357 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006358
Weiyin Jiangd4633762018-03-16 12:05:03 +08006359 // Adjustment accounts for A2dp encoder latency with non offload usecases
6360 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006361 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006362 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6363 if (signed_frames >= frames_temp)
6364 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006365 }
6366
6367 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006368 *frames = signed_frames;
6369 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006370 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006371 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6372 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006373 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306374 *frames = out->written;
6375 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306376 if (is_offload_usecase(out->usecase))
6377 ret = -EINVAL;
6378 else
6379 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006380 }
6381 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006382 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006383 return ret;
6384}
6385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006386static int out_set_callback(struct audio_stream_out *stream,
6387 stream_callback_t callback, void *cookie)
6388{
6389 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006390 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006391
6392 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006393 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006394 out->client_callback = callback;
6395 out->client_cookie = cookie;
6396 if (out->adsp_hdlr_stream_handle) {
6397 ret = audio_extn_adsp_hdlr_stream_set_callback(
6398 out->adsp_hdlr_stream_handle,
6399 callback,
6400 cookie);
6401 if (ret)
6402 ALOGW("%s:adsp hdlr callback registration failed %d",
6403 __func__, ret);
6404 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006405 pthread_mutex_unlock(&out->lock);
6406 return 0;
6407}
6408
6409static int out_pause(struct audio_stream_out* stream)
6410{
6411 struct stream_out *out = (struct stream_out *)stream;
6412 int status = -ENOSYS;
6413 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006414 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006415 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306416 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006417 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006418 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006419 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306420 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306421 status = compress_pause(out->compr);
6422
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006423 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006424
Mingming Yin21854652016-04-13 11:54:02 -07006425 if (audio_extn_passthru_is_active()) {
6426 ALOGV("offload use case, pause passthru");
6427 audio_extn_passthru_on_pause(out);
6428 }
6429
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306430 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006431 audio_extn_dts_notify_playback_state(out->usecase, 0,
6432 out->sample_rate, popcount(out->channel_mask),
6433 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006434 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006435 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006436 pthread_mutex_unlock(&out->lock);
6437 }
6438 return status;
6439}
6440
6441static int out_resume(struct audio_stream_out* stream)
6442{
6443 struct stream_out *out = (struct stream_out *)stream;
6444 int status = -ENOSYS;
6445 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006446 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006447 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306448 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006449 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006450 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006451 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306452 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306453 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006454 }
6455 if (!status) {
6456 out->offload_state = OFFLOAD_STATE_PLAYING;
6457 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306458 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006459 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6460 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006461 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006462 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006463 pthread_mutex_unlock(&out->lock);
6464 }
6465 return status;
6466}
6467
6468static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6469{
6470 struct stream_out *out = (struct stream_out *)stream;
6471 int status = -ENOSYS;
6472 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006473 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006474 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006475 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6476 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6477 else
6478 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6479 pthread_mutex_unlock(&out->lock);
6480 }
6481 return status;
6482}
6483
6484static int out_flush(struct audio_stream_out* stream)
6485{
6486 struct stream_out *out = (struct stream_out *)stream;
6487 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006488 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006489 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006490 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006491 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006492 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6493 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006494 } else {
6495 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6496 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006497 out->written = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006498 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006499 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006500 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006501 return 0;
6502 }
6503 return -ENOSYS;
6504}
6505
Haynes Mathew George16081042017-05-31 17:16:49 -07006506static int out_stop(const struct audio_stream_out* stream)
6507{
6508 struct stream_out *out = (struct stream_out *)stream;
6509 struct audio_device *adev = out->dev;
6510 int ret = -ENOSYS;
6511
6512 ALOGV("%s", __func__);
6513 pthread_mutex_lock(&adev->lock);
6514 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6515 out->playback_started && out->pcm != NULL) {
6516 pcm_stop(out->pcm);
6517 ret = stop_output_stream(out);
6518 out->playback_started = false;
6519 }
6520 pthread_mutex_unlock(&adev->lock);
6521 return ret;
6522}
6523
6524static int out_start(const struct audio_stream_out* stream)
6525{
6526 struct stream_out *out = (struct stream_out *)stream;
6527 struct audio_device *adev = out->dev;
6528 int ret = -ENOSYS;
6529
6530 ALOGV("%s", __func__);
6531 pthread_mutex_lock(&adev->lock);
6532 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6533 !out->playback_started && out->pcm != NULL) {
6534 ret = start_output_stream(out);
6535 if (ret == 0) {
6536 out->playback_started = true;
6537 }
6538 }
6539 pthread_mutex_unlock(&adev->lock);
6540 return ret;
6541}
6542
6543/*
6544 * Modify config->period_count based on min_size_frames
6545 */
6546static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6547{
6548 int periodCountRequested = (min_size_frames + config->period_size - 1)
6549 / config->period_size;
6550 int periodCount = MMAP_PERIOD_COUNT_MIN;
6551
6552 ALOGV("%s original config.period_size = %d config.period_count = %d",
6553 __func__, config->period_size, config->period_count);
6554
6555 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6556 periodCount *= 2;
6557 }
6558 config->period_count = periodCount;
6559
6560 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6561}
6562
Phil Burkfe17efd2019-03-25 10:23:35 -07006563// Read offset for the positional timestamp from a persistent vendor property.
6564// This is to workaround apparent inaccuracies in the timing information that
6565// is used by the AAudio timing model. The inaccuracies can cause glitches.
6566static int64_t get_mmap_out_time_offset() {
6567 const int32_t kDefaultOffsetMicros = 0;
6568 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006569 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006570 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6571 return mmap_time_offset_micros * (int64_t)1000;
6572}
6573
Haynes Mathew George16081042017-05-31 17:16:49 -07006574static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6575 int32_t min_size_frames,
6576 struct audio_mmap_buffer_info *info)
6577{
6578 struct stream_out *out = (struct stream_out *)stream;
6579 struct audio_device *adev = out->dev;
6580 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006581 unsigned int offset1 = 0;
6582 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006583 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006584 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006585 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006586
Arun Mirpuri5d170872019-03-26 13:21:31 -07006587 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306588 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006589 pthread_mutex_lock(&adev->lock);
6590
Sharad Sanglec6f32552018-05-04 16:15:38 +05306591 if (CARD_STATUS_OFFLINE == out->card_status ||
6592 CARD_STATUS_OFFLINE == adev->card_status) {
6593 ALOGW("out->card_status or adev->card_status offline, try again");
6594 ret = -EIO;
6595 goto exit;
6596 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306597 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006598 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6599 ret = -EINVAL;
6600 goto exit;
6601 }
6602 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6603 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6604 ret = -ENOSYS;
6605 goto exit;
6606 }
6607 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6608 if (out->pcm_device_id < 0) {
6609 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6610 __func__, out->pcm_device_id, out->usecase);
6611 ret = -EINVAL;
6612 goto exit;
6613 }
6614
6615 adjust_mmap_period_count(&out->config, min_size_frames);
6616
Arun Mirpuri5d170872019-03-26 13:21:31 -07006617 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006618 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6619 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6620 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306621 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306622 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6623 out->card_status = CARD_STATUS_OFFLINE;
6624 adev->card_status = CARD_STATUS_OFFLINE;
6625 ret = -EIO;
6626 goto exit;
6627 }
6628
Haynes Mathew George16081042017-05-31 17:16:49 -07006629 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6630 step = "open";
6631 ret = -ENODEV;
6632 goto exit;
6633 }
6634 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6635 if (ret < 0) {
6636 step = "begin";
6637 goto exit;
6638 }
juyuchen626833d2019-06-04 16:48:02 +08006639
6640 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006641 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006642 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006643 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006644 ret = platform_get_mmap_data_fd(adev->platform,
6645 out->pcm_device_id, 0 /*playback*/,
6646 &info->shared_memory_fd,
6647 &mmap_size);
6648 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006649 // Fall back to non exclusive mode
6650 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6651 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006652 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6653 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6654
Arun Mirpuri5d170872019-03-26 13:21:31 -07006655 if (mmap_size < buffer_size) {
6656 step = "mmap";
6657 goto exit;
6658 }
juyuchen626833d2019-06-04 16:48:02 +08006659 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006660 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006661 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006662 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006663
6664 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6665 if (ret < 0) {
6666 step = "commit";
6667 goto exit;
6668 }
6669
Phil Burkfe17efd2019-03-25 10:23:35 -07006670 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6671
Haynes Mathew George16081042017-05-31 17:16:49 -07006672 out->standby = false;
6673 ret = 0;
6674
Arun Mirpuri5d170872019-03-26 13:21:31 -07006675 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006676 __func__, info->shared_memory_address, info->buffer_size_frames);
6677
6678exit:
6679 if (ret != 0) {
6680 if (out->pcm == NULL) {
6681 ALOGE("%s: %s - %d", __func__, step, ret);
6682 } else {
6683 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6684 pcm_close(out->pcm);
6685 out->pcm = NULL;
6686 }
6687 }
6688 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306689 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006690 return ret;
6691}
6692
6693static int out_get_mmap_position(const struct audio_stream_out *stream,
6694 struct audio_mmap_position *position)
6695{
6696 struct stream_out *out = (struct stream_out *)stream;
6697 ALOGVV("%s", __func__);
6698 if (position == NULL) {
6699 return -EINVAL;
6700 }
6701 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006702 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006703 return -ENOSYS;
6704 }
6705 if (out->pcm == NULL) {
6706 return -ENOSYS;
6707 }
6708
6709 struct timespec ts = { 0, 0 };
6710 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6711 if (ret < 0) {
6712 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6713 return ret;
6714 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006715 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6716 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006717 return 0;
6718}
6719
6720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721/** audio_stream_in implementation **/
6722static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6723{
6724 struct stream_in *in = (struct stream_in *)stream;
6725
6726 return in->config.rate;
6727}
6728
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006729static int in_set_sample_rate(struct audio_stream *stream __unused,
6730 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006731{
6732 return -ENOSYS;
6733}
6734
6735static size_t in_get_buffer_size(const struct audio_stream *stream)
6736{
6737 struct stream_in *in = (struct stream_in *)stream;
6738
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006739 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6740 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006741 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6742 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306743 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306744 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006745
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006746 return in->config.period_size * in->af_period_multiplier *
6747 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006748}
6749
6750static uint32_t in_get_channels(const struct audio_stream *stream)
6751{
6752 struct stream_in *in = (struct stream_in *)stream;
6753
6754 return in->channel_mask;
6755}
6756
6757static audio_format_t in_get_format(const struct audio_stream *stream)
6758{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006759 struct stream_in *in = (struct stream_in *)stream;
6760
6761 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006762}
6763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006764static int in_set_format(struct audio_stream *stream __unused,
6765 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006766{
6767 return -ENOSYS;
6768}
6769
6770static int in_standby(struct audio_stream *stream)
6771{
6772 struct stream_in *in = (struct stream_in *)stream;
6773 struct audio_device *adev = in->dev;
6774 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306775 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6776 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006777 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306778
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006779 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006780 if (!in->standby && in->is_st_session) {
6781 ALOGD("%s: sound trigger pcm stop lab", __func__);
6782 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006783 if (adev->num_va_sessions > 0)
6784 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006785 in->standby = 1;
6786 }
6787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006788 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006789 if (adev->adm_deregister_stream)
6790 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6791
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006792 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006793 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006794 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006795 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006796 voice_extn_compress_voip_close_input_stream(stream);
6797 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006798 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6799 do_stop = in->capture_started;
6800 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006801 if (in->mmap_shared_memory_fd >= 0) {
6802 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6803 __func__, in->mmap_shared_memory_fd);
6804 close(in->mmap_shared_memory_fd);
6805 in->mmap_shared_memory_fd = -1;
6806 }
Zhou Songa8895042016-07-05 17:54:22 +08006807 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306808 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306809 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006810 }
6811
Arun Mirpuri5d170872019-03-26 13:21:31 -07006812 if (in->pcm) {
6813 ATRACE_BEGIN("pcm_in_close");
6814 pcm_close(in->pcm);
6815 ATRACE_END();
6816 in->pcm = NULL;
6817 }
6818
Carter Hsu2e429db2019-05-14 18:50:52 +08006819 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006820 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006821
George Gao3018ede2019-10-23 13:23:00 -07006822 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6823 if (adev->num_va_sessions > 0)
6824 adev->num_va_sessions--;
6825 }
Quinn Malef6050362019-01-30 15:55:40 -08006826
Eric Laurent150dbfe2013-02-27 14:31:02 -08006827 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006828 }
6829 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006830 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006831 return status;
6832}
6833
Aalique Grahame22e49102018-12-18 14:23:57 -08006834static int in_dump(const struct audio_stream *stream,
6835 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836{
Aalique Grahame22e49102018-12-18 14:23:57 -08006837 struct stream_in *in = (struct stream_in *)stream;
6838
6839 // We try to get the lock for consistency,
6840 // but it isn't necessary for these variables.
6841 // If we're not in standby, we may be blocked on a read.
6842 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6843 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6844 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6845 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6846
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006847 char buffer[256]; // for statistics formatting
6848 if (in->start_latency_ms.n > 0) {
6849 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6850 dprintf(fd, " Start latency ms: %s\n", buffer);
6851 }
6852
Aalique Grahame22e49102018-12-18 14:23:57 -08006853 if (locked) {
6854 pthread_mutex_unlock(&in->lock);
6855 }
6856
6857 // dump error info
6858 (void)error_log_dump(
6859 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861 return 0;
6862}
6863
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306864static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6865{
6866 if (!stream || !parms)
6867 return;
6868
6869 struct stream_in *in = (struct stream_in *)stream;
6870 struct audio_device *adev = in->dev;
6871
6872 card_status_t status;
6873 int card;
6874 if (parse_snd_card_status(parms, &card, &status) < 0)
6875 return;
6876
6877 pthread_mutex_lock(&adev->lock);
6878 bool valid_cb = (card == adev->snd_card);
6879 pthread_mutex_unlock(&adev->lock);
6880
6881 if (!valid_cb)
6882 return;
6883
6884 lock_input_stream(in);
6885 if (in->card_status != status)
6886 in->card_status = status;
6887 pthread_mutex_unlock(&in->lock);
6888
6889 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6890 use_case_table[in->usecase],
6891 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6892
6893 // a better solution would be to report error back to AF and let
6894 // it put the stream to standby
6895 if (status == CARD_STATUS_OFFLINE)
6896 in_standby(&in->stream.common);
6897
6898 return;
6899}
6900
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006901int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006902 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006903 audio_source_t source)
6904{
6905 struct audio_device *adev = in->dev;
6906 int ret = 0;
6907
6908 lock_input_stream(in);
6909 pthread_mutex_lock(&adev->lock);
6910
6911 /* no audio source uses val == 0 */
6912 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6913 in->source = source;
6914 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6915 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6916 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6917 (in->config.rate == 8000 || in->config.rate == 16000 ||
6918 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6919 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6920 ret = voice_extn_compress_voip_open_input_stream(in);
6921 if (ret != 0) {
6922 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6923 __func__, ret);
6924 }
6925 }
6926 }
6927
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006928 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6929 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006930 // Workaround: If routing to an non existing usb device, fail gracefully
6931 // The routing request will otherwise block during 10 second
6932 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006933 struct str_parms *usb_addr =
6934 str_parms_create_str(get_usb_device_address(devices));
6935 if (is_usb_in_device_type(devices) && usb_addr &&
6936 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006937 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6938 ret = -ENOSYS;
6939 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006940 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006941 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006942 if (!in->standby && !in->is_st_session) {
6943 ALOGV("update input routing change");
6944 // inform adm before actual routing to prevent glitches.
6945 if (adev->adm_on_routing_change) {
6946 adev->adm_on_routing_change(adev->adm_data,
6947 in->capture_handle);
6948 ret = select_devices(adev, in->usecase);
6949 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6950 adev->adm_routing_changed = true;
6951 }
6952 }
6953 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006954 if (usb_addr)
6955 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006956 }
6957 pthread_mutex_unlock(&adev->lock);
6958 pthread_mutex_unlock(&in->lock);
6959
6960 ALOGD("%s: exit: status(%d)", __func__, ret);
6961 return ret;
6962}
6963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006964static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6965{
6966 struct stream_in *in = (struct stream_in *)stream;
6967 struct audio_device *adev = in->dev;
6968 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006969 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306970 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006971
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306972 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973 parms = str_parms_create_str(kvpairs);
6974
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306975 if (!parms)
6976 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006977 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006978 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006979
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306980 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6981 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306982 strlcpy(in->profile, value, sizeof(in->profile));
6983 ALOGV("updating stream profile with value '%s'", in->profile);
6984 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6985 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006986 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306987 in->sample_rate, in->bit_width,
6988 in->profile, &in->app_type_cfg);
6989 }
6990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006991 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006992 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006993
6994 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306995error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306996 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006997}
6998
6999static char* in_get_parameters(const struct audio_stream *stream,
7000 const char *keys)
7001{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007002 struct stream_in *in = (struct stream_in *)stream;
7003 struct str_parms *query = str_parms_create_str(keys);
7004 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007005 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007006
7007 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007008 if (reply) {
7009 str_parms_destroy(reply);
7010 }
7011 if (query) {
7012 str_parms_destroy(query);
7013 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007014 ALOGE("in_get_parameters: failed to create query or reply");
7015 return NULL;
7016 }
7017
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007018 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007019
7020 voice_extn_in_get_parameters(in, query, reply);
7021
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007022 stream_get_parameter_channels(query, reply,
7023 &in->supported_channel_masks[0]);
7024 stream_get_parameter_formats(query, reply,
7025 &in->supported_formats[0]);
7026 stream_get_parameter_rates(query, reply,
7027 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007028 str = str_parms_to_str(reply);
7029 str_parms_destroy(query);
7030 str_parms_destroy(reply);
7031
7032 ALOGV("%s: exit: returns - %s", __func__, str);
7033 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007034}
7035
Aalique Grahame22e49102018-12-18 14:23:57 -08007036static int in_set_gain(struct audio_stream_in *stream,
7037 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007038{
Aalique Grahame22e49102018-12-18 14:23:57 -08007039 struct stream_in *in = (struct stream_in *)stream;
7040 char mixer_ctl_name[128];
7041 struct mixer_ctl *ctl;
7042 int ctl_value;
7043
7044 ALOGV("%s: gain %f", __func__, gain);
7045
7046 if (stream == NULL)
7047 return -EINVAL;
7048
7049 /* in_set_gain() only used to silence MMAP capture for now */
7050 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7051 return -ENOSYS;
7052
7053 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7054
7055 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7056 if (!ctl) {
7057 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7058 __func__, mixer_ctl_name);
7059 return -ENOSYS;
7060 }
7061
7062 if (gain < RECORD_GAIN_MIN)
7063 gain = RECORD_GAIN_MIN;
7064 else if (gain > RECORD_GAIN_MAX)
7065 gain = RECORD_GAIN_MAX;
7066 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7067
7068 mixer_ctl_set_value(ctl, 0, ctl_value);
7069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007070 return 0;
7071}
7072
7073static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7074 size_t bytes)
7075{
7076 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307077
7078 if (in == NULL) {
7079 ALOGE("%s: stream_in ptr is NULL", __func__);
7080 return -EINVAL;
7081 }
7082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007083 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307084 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307085 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007086
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007087 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307088
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007089 if (in->is_st_session) {
7090 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7091 /* Read from sound trigger HAL */
7092 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007093 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007094 if (adev->num_va_sessions < UINT_MAX)
7095 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007096 in->standby = 0;
7097 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007098 pthread_mutex_unlock(&in->lock);
7099 return bytes;
7100 }
7101
Haynes Mathew George16081042017-05-31 17:16:49 -07007102 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7103 ret = -ENOSYS;
7104 goto exit;
7105 }
7106
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007107 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7108 !in->standby && adev->adm_routing_changed) {
7109 ret = -ENOSYS;
7110 goto exit;
7111 }
7112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007114 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7115
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007116 pthread_mutex_lock(&adev->lock);
7117 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7118 ret = voice_extn_compress_voip_start_input_stream(in);
7119 else
7120 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007121 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7122 if (adev->num_va_sessions < UINT_MAX)
7123 adev->num_va_sessions++;
7124 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007125 pthread_mutex_unlock(&adev->lock);
7126 if (ret != 0) {
7127 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007128 }
7129 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007130
7131 // log startup time in ms.
7132 simple_stats_log(
7133 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007135
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307136 /* Avoid read if capture_stopped is set */
7137 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7138 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7139 ret = -EINVAL;
7140 goto exit;
7141 }
7142
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007143 // what's the duration requested by the client?
7144 long ns = 0;
7145
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307146 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007147 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7148 in->config.rate;
7149
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007150 ret = request_in_focus(in, ns);
7151 if (ret != 0)
7152 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007153 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007154
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307155 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307156 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7157 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307158 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007159 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307160 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007161 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007162 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007163 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007164 } else if (audio_extn_ffv_get_stream() == in) {
7165 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307166 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007167 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307168 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7169 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7170 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7171 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307172 ret = -EINVAL;
7173 goto exit;
7174 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307175 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307176 ret = -errno;
7177 }
7178 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307179 /* bytes read is always set to bytes for non compress usecases */
7180 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007181 }
7182
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007183 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007185 /*
Quinn Malef6050362019-01-30 15:55:40 -08007186 * Instead of writing zeroes here, we could trust the hardware to always
7187 * provide zeroes when muted. This is also muted with voice recognition
7188 * usecases so that other clients do not have access to voice recognition
7189 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007190 */
Quinn Malef6050362019-01-30 15:55:40 -08007191 if ((ret == 0 && voice_get_mic_mute(adev) &&
7192 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007193 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7194 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007195 (adev->num_va_sessions &&
7196 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7197 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7198 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007199 memset(buffer, 0, bytes);
7200
7201exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307202 frame_size = audio_stream_in_frame_size(stream);
7203 if (frame_size > 0)
7204 in->frames_read += bytes_read/frame_size;
7205
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007206 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307207 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007208 pthread_mutex_unlock(&in->lock);
7209
7210 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307211 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307212 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307213 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307214 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307215 in->standby = true;
7216 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307217 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307218 bytes_read = bytes;
7219 memset(buffer, 0, bytes);
7220 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007221 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007222 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7223 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007224 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307225 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307226 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007227 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307228 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007229}
7230
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007231static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007232{
7233 return 0;
7234}
7235
Aalique Grahame22e49102018-12-18 14:23:57 -08007236static int in_get_capture_position(const struct audio_stream_in *stream,
7237 int64_t *frames, int64_t *time)
7238{
7239 if (stream == NULL || frames == NULL || time == NULL) {
7240 return -EINVAL;
7241 }
7242 struct stream_in *in = (struct stream_in *)stream;
7243 int ret = -ENOSYS;
7244
7245 lock_input_stream(in);
7246 // note: ST sessions do not close the alsa pcm driver synchronously
7247 // on standby. Therefore, we may return an error even though the
7248 // pcm stream is still opened.
7249 if (in->standby) {
7250 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7251 "%s stream in standby but pcm not NULL for non ST session", __func__);
7252 goto exit;
7253 }
7254 if (in->pcm) {
7255 struct timespec timestamp;
7256 unsigned int avail;
7257 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7258 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007259 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007260 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007261 ret = 0;
7262 }
7263 }
7264exit:
7265 pthread_mutex_unlock(&in->lock);
7266 return ret;
7267}
7268
Carter Hsu2e429db2019-05-14 18:50:52 +08007269static int in_update_effect_list(bool add, effect_handle_t effect,
7270 struct listnode *head)
7271{
7272 struct listnode *node;
7273 struct in_effect_list *elist = NULL;
7274 struct in_effect_list *target = NULL;
7275 int ret = 0;
7276
7277 if (!head)
7278 return ret;
7279
7280 list_for_each(node, head) {
7281 elist = node_to_item(node, struct in_effect_list, list);
7282 if (elist->handle == effect) {
7283 target = elist;
7284 break;
7285 }
7286 }
7287
7288 if (add) {
7289 if (target) {
7290 ALOGD("effect %p already exist", effect);
7291 return ret;
7292 }
7293
7294 target = (struct in_effect_list *)
7295 calloc(1, sizeof(struct in_effect_list));
7296
7297 if (!target) {
7298 ALOGE("%s:fail to allocate memory", __func__);
7299 return -ENOMEM;
7300 }
7301
7302 target->handle = effect;
7303 list_add_tail(head, &target->list);
7304 } else {
7305 if (target) {
7306 list_remove(&target->list);
7307 free(target);
7308 }
7309 }
7310
7311 return ret;
7312}
7313
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007314static int add_remove_audio_effect(const struct audio_stream *stream,
7315 effect_handle_t effect,
7316 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007317{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007318 struct stream_in *in = (struct stream_in *)stream;
7319 int status = 0;
7320 effect_descriptor_t desc;
7321
7322 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007323 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7324
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007325 if (status != 0)
7326 return status;
7327
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007328 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007329 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007330 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007331 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7332 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007333 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007334
7335 in_update_effect_list(enable, effect, &in->aec_list);
7336 enable = !list_empty(&in->aec_list);
7337 if (enable == in->enable_aec)
7338 goto exit;
7339
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007340 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007341 ALOGD("AEC enable %d", enable);
7342
Aalique Grahame22e49102018-12-18 14:23:57 -08007343 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7344 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7345 in->dev->enable_voicerx = enable;
7346 struct audio_usecase *usecase;
7347 struct listnode *node;
7348 list_for_each(node, &in->dev->usecase_list) {
7349 usecase = node_to_item(node, struct audio_usecase, list);
7350 if (usecase->type == PCM_PLAYBACK)
7351 select_devices(in->dev, usecase->id);
7352 }
7353 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007354 if (!in->standby) {
7355 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7356 select_devices(in->dev, in->usecase);
7357 }
7358
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007359 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007360 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7361
7362 in_update_effect_list(enable, effect, &in->ns_list);
7363 enable = !list_empty(&in->ns_list);
7364 if (enable == in->enable_ns)
7365 goto exit;
7366
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007367 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007368 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007369 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007370 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7371 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007372 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7373 select_devices(in->dev, in->usecase);
7374 } else
7375 select_devices(in->dev, in->usecase);
7376 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007377 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007378exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007379 pthread_mutex_unlock(&in->dev->lock);
7380 pthread_mutex_unlock(&in->lock);
7381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007382 return 0;
7383}
7384
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007385static int in_add_audio_effect(const struct audio_stream *stream,
7386 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007387{
Eric Laurent994a6932013-07-17 11:51:42 -07007388 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007389 return add_remove_audio_effect(stream, effect, true);
7390}
7391
7392static int in_remove_audio_effect(const struct audio_stream *stream,
7393 effect_handle_t effect)
7394{
Eric Laurent994a6932013-07-17 11:51:42 -07007395 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007396 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007397}
7398
Derek Chenf939fb72018-11-13 13:34:41 -08007399streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7400 audio_io_handle_t input)
7401{
7402 struct listnode *node;
7403
7404 list_for_each(node, &dev->active_inputs_list) {
7405 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7406 streams_input_ctxt_t,
7407 list);
7408 if (in_ctxt->input->capture_handle == input) {
7409 return in_ctxt;
7410 }
7411 }
7412 return NULL;
7413}
7414
7415streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7416 audio_io_handle_t output)
7417{
7418 struct listnode *node;
7419
7420 list_for_each(node, &dev->active_outputs_list) {
7421 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7422 streams_output_ctxt_t,
7423 list);
7424 if (out_ctxt->output->handle == output) {
7425 return out_ctxt;
7426 }
7427 }
7428 return NULL;
7429}
7430
Haynes Mathew George16081042017-05-31 17:16:49 -07007431static int in_stop(const struct audio_stream_in* stream)
7432{
7433 struct stream_in *in = (struct stream_in *)stream;
7434 struct audio_device *adev = in->dev;
7435
7436 int ret = -ENOSYS;
7437 ALOGV("%s", __func__);
7438 pthread_mutex_lock(&adev->lock);
7439 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7440 in->capture_started && in->pcm != NULL) {
7441 pcm_stop(in->pcm);
7442 ret = stop_input_stream(in);
7443 in->capture_started = false;
7444 }
7445 pthread_mutex_unlock(&adev->lock);
7446 return ret;
7447}
7448
7449static int in_start(const struct audio_stream_in* stream)
7450{
7451 struct stream_in *in = (struct stream_in *)stream;
7452 struct audio_device *adev = in->dev;
7453 int ret = -ENOSYS;
7454
7455 ALOGV("%s in %p", __func__, in);
7456 pthread_mutex_lock(&adev->lock);
7457 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7458 !in->capture_started && in->pcm != NULL) {
7459 if (!in->capture_started) {
7460 ret = start_input_stream(in);
7461 if (ret == 0) {
7462 in->capture_started = true;
7463 }
7464 }
7465 }
7466 pthread_mutex_unlock(&adev->lock);
7467 return ret;
7468}
7469
Phil Burke0a86d12019-02-16 22:28:11 -08007470// Read offset for the positional timestamp from a persistent vendor property.
7471// This is to workaround apparent inaccuracies in the timing information that
7472// is used by the AAudio timing model. The inaccuracies can cause glitches.
7473static int64_t in_get_mmap_time_offset() {
7474 const int32_t kDefaultOffsetMicros = 0;
7475 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007476 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007477 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7478 return mmap_time_offset_micros * (int64_t)1000;
7479}
7480
Haynes Mathew George16081042017-05-31 17:16:49 -07007481static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7482 int32_t min_size_frames,
7483 struct audio_mmap_buffer_info *info)
7484{
7485 struct stream_in *in = (struct stream_in *)stream;
7486 struct audio_device *adev = in->dev;
7487 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007488 unsigned int offset1 = 0;
7489 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007490 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007491 uint32_t mmap_size = 0;
7492 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007493
7494 pthread_mutex_lock(&adev->lock);
7495 ALOGV("%s in %p", __func__, in);
7496
Sharad Sanglec6f32552018-05-04 16:15:38 +05307497 if (CARD_STATUS_OFFLINE == in->card_status||
7498 CARD_STATUS_OFFLINE == adev->card_status) {
7499 ALOGW("in->card_status or adev->card_status offline, try again");
7500 ret = -EIO;
7501 goto exit;
7502 }
7503
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307504 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007505 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7506 ret = -EINVAL;
7507 goto exit;
7508 }
7509 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7510 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7511 ALOGV("%s in %p", __func__, in);
7512 ret = -ENOSYS;
7513 goto exit;
7514 }
7515 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7516 if (in->pcm_device_id < 0) {
7517 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7518 __func__, in->pcm_device_id, in->usecase);
7519 ret = -EINVAL;
7520 goto exit;
7521 }
7522
7523 adjust_mmap_period_count(&in->config, min_size_frames);
7524
7525 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7526 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7527 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7528 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307529 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307530 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7531 in->card_status = CARD_STATUS_OFFLINE;
7532 adev->card_status = CARD_STATUS_OFFLINE;
7533 ret = -EIO;
7534 goto exit;
7535 }
7536
Haynes Mathew George16081042017-05-31 17:16:49 -07007537 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7538 step = "open";
7539 ret = -ENODEV;
7540 goto exit;
7541 }
7542
7543 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7544 if (ret < 0) {
7545 step = "begin";
7546 goto exit;
7547 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007548
juyuchen626833d2019-06-04 16:48:02 +08007549 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007550 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7551 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7552 info->burst_size_frames = in->config.period_size;
7553 ret = platform_get_mmap_data_fd(adev->platform,
7554 in->pcm_device_id, 1 /*capture*/,
7555 &info->shared_memory_fd,
7556 &mmap_size);
7557 if (ret < 0) {
7558 // Fall back to non exclusive mode
7559 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7560 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007561 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7562 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7563
Arun Mirpuri5d170872019-03-26 13:21:31 -07007564 if (mmap_size < buffer_size) {
7565 step = "mmap";
7566 goto exit;
7567 }
juyuchen626833d2019-06-04 16:48:02 +08007568 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007569 }
7570
7571 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007572
7573 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7574 if (ret < 0) {
7575 step = "commit";
7576 goto exit;
7577 }
7578
Phil Burke0a86d12019-02-16 22:28:11 -08007579 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7580
Haynes Mathew George16081042017-05-31 17:16:49 -07007581 in->standby = false;
7582 ret = 0;
7583
7584 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7585 __func__, info->shared_memory_address, info->buffer_size_frames);
7586
7587exit:
7588 if (ret != 0) {
7589 if (in->pcm == NULL) {
7590 ALOGE("%s: %s - %d", __func__, step, ret);
7591 } else {
7592 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7593 pcm_close(in->pcm);
7594 in->pcm = NULL;
7595 }
7596 }
7597 pthread_mutex_unlock(&adev->lock);
7598 return ret;
7599}
7600
7601static int in_get_mmap_position(const struct audio_stream_in *stream,
7602 struct audio_mmap_position *position)
7603{
7604 struct stream_in *in = (struct stream_in *)stream;
7605 ALOGVV("%s", __func__);
7606 if (position == NULL) {
7607 return -EINVAL;
7608 }
7609 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7610 return -ENOSYS;
7611 }
7612 if (in->pcm == NULL) {
7613 return -ENOSYS;
7614 }
7615 struct timespec ts = { 0, 0 };
7616 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7617 if (ret < 0) {
7618 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7619 return ret;
7620 }
Phil Burke0a86d12019-02-16 22:28:11 -08007621 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7622 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007623 return 0;
7624}
7625
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307626static int in_get_active_microphones(const struct audio_stream_in *stream,
7627 struct audio_microphone_characteristic_t *mic_array,
7628 size_t *mic_count) {
7629 struct stream_in *in = (struct stream_in *)stream;
7630 struct audio_device *adev = in->dev;
7631 ALOGVV("%s", __func__);
7632
7633 lock_input_stream(in);
7634 pthread_mutex_lock(&adev->lock);
7635 int ret = platform_get_active_microphones(adev->platform,
7636 audio_channel_count_from_in_mask(in->channel_mask),
7637 in->usecase, mic_array, mic_count);
7638 pthread_mutex_unlock(&adev->lock);
7639 pthread_mutex_unlock(&in->lock);
7640
7641 return ret;
7642}
7643
7644static int adev_get_microphones(const struct audio_hw_device *dev,
7645 struct audio_microphone_characteristic_t *mic_array,
7646 size_t *mic_count) {
7647 struct audio_device *adev = (struct audio_device *)dev;
7648 ALOGVV("%s", __func__);
7649
7650 pthread_mutex_lock(&adev->lock);
7651 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7652 pthread_mutex_unlock(&adev->lock);
7653
7654 return ret;
7655}
juyuchendb308c22019-01-21 11:57:17 -07007656
7657static void in_update_sink_metadata(struct audio_stream_in *stream,
7658 const struct sink_metadata *sink_metadata) {
7659
7660 if (stream == NULL
7661 || sink_metadata == NULL
7662 || sink_metadata->tracks == NULL) {
7663 return;
7664 }
7665
7666 int error = 0;
7667 struct stream_in *in = (struct stream_in *)stream;
7668 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007669 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007670 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007671
7672 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007673
7674 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007675 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007676
7677 lock_input_stream(in);
7678 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007679 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007680
Zhou Song62ea0282020-03-22 19:53:01 +08007681 is_ha_usecase = adev->ha_proxy_enable ?
7682 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7683 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7684 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007685 && adev->voice_tx_output != NULL) {
7686 /* Use the rx device from afe-proxy record to route voice call because
7687 there is no routing if tx device is on primary hal and rx device
7688 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007689 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007690
7691 if (!voice_is_call_state_active(adev)) {
7692 if (adev->mode == AUDIO_MODE_IN_CALL) {
7693 adev->current_call_output = adev->voice_tx_output;
7694 error = voice_start_call(adev);
7695 if (error != 0)
7696 ALOGE("%s: start voice call failed %d", __func__, error);
7697 }
7698 } else {
7699 adev->current_call_output = adev->voice_tx_output;
7700 voice_update_devices_for_all_voice_usecases(adev);
7701 }
7702 }
7703
7704 pthread_mutex_unlock(&adev->lock);
7705 pthread_mutex_unlock(&in->lock);
7706}
7707
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307708int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007709 audio_io_handle_t handle,
7710 audio_devices_t devices,
7711 audio_output_flags_t flags,
7712 struct audio_config *config,
7713 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007714 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007715{
7716 struct audio_device *adev = (struct audio_device *)dev;
7717 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307718 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007719 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007720 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307721 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007722 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7723 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7724 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7725 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007726 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007727 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7728 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007729 bool force_haptic_path =
7730 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007731 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007732#ifdef AUDIO_GKI_ENABLED
7733 __s32 *generic_dec;
7734#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007735
kunleizdff872d2018-08-20 14:40:33 +08007736 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007737 is_usb_dev = false;
7738 devices = AUDIO_DEVICE_OUT_SPEAKER;
7739 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7740 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007741 if (config->format == AUDIO_FORMAT_DEFAULT)
7742 config->format = AUDIO_FORMAT_PCM_16_BIT;
7743 if (config->sample_rate == 0)
7744 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7745 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7746 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007747 }
7748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007749 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307750
Rahul Sharma99770982019-03-06 17:05:26 +05307751 pthread_mutex_lock(&adev->lock);
7752 if (out_get_stream(adev, handle) != NULL) {
7753 ALOGW("%s, output stream already opened", __func__);
7754 ret = -EEXIST;
7755 }
7756 pthread_mutex_unlock(&adev->lock);
7757 if (ret)
7758 return ret;
7759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007760 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7761
Mingming Yin3a941d42016-02-17 18:08:05 -08007762 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007763 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7764 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307765
7766
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007767 if (!out) {
7768 return -ENOMEM;
7769 }
7770
Haynes Mathew George204045b2015-02-25 20:32:03 -08007771 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007772 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007773 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007774 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007775 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007777 if (devices == AUDIO_DEVICE_NONE)
7778 devices = AUDIO_DEVICE_OUT_SPEAKER;
7779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007780 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007781 list_init(&out->device_list);
7782 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007783 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007784 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007785 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307786 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307787 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7788 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7789 else
7790 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007791 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007792 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007793 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307794 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307795 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307796 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007797 out->hal_output_suspend_supported = 0;
7798 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307799 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307800 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307801 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007802 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007803
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307804 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307805 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007806 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7807
Aalique Grahame22e49102018-12-18 14:23:57 -08007808 if (direct_dev &&
7809 (audio_is_linear_pcm(out->format) ||
7810 config->format == AUDIO_FORMAT_DEFAULT) &&
7811 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7812 audio_format_t req_format = config->format;
7813 audio_channel_mask_t req_channel_mask = config->channel_mask;
7814 uint32_t req_sample_rate = config->sample_rate;
7815
7816 pthread_mutex_lock(&adev->lock);
7817 if (is_hdmi) {
7818 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7819 ret = read_hdmi_sink_caps(out);
7820 if (config->sample_rate == 0)
7821 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7822 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7823 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7824 if (config->format == AUDIO_FORMAT_DEFAULT)
7825 config->format = AUDIO_FORMAT_PCM_16_BIT;
7826 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007827 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7828 &config->format,
7829 &out->supported_formats[0],
7830 MAX_SUPPORTED_FORMATS,
7831 &config->channel_mask,
7832 &out->supported_channel_masks[0],
7833 MAX_SUPPORTED_CHANNEL_MASKS,
7834 &config->sample_rate,
7835 &out->supported_sample_rates[0],
7836 MAX_SUPPORTED_SAMPLE_RATES);
7837 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007838 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007839
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007840 pthread_mutex_unlock(&adev->lock);
7841 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007842 if (ret == -ENOSYS) {
7843 /* ignore and go with default */
7844 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007845 }
7846 // For MMAP NO IRQ, allow conversions in ADSP
7847 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7848 goto error_open;
7849 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007850 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007851 goto error_open;
7852 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007853
7854 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7855 config->sample_rate = req_sample_rate;
7856 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7857 config->channel_mask = req_channel_mask;
7858 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7859 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007860 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007861
7862 out->sample_rate = config->sample_rate;
7863 out->channel_mask = config->channel_mask;
7864 out->format = config->format;
7865 if (is_hdmi) {
7866 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7867 out->config = pcm_config_hdmi_multi;
7868 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7869 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7870 out->config = pcm_config_mmap_playback;
7871 out->stream.start = out_start;
7872 out->stream.stop = out_stop;
7873 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7874 out->stream.get_mmap_position = out_get_mmap_position;
7875 } else {
7876 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7877 out->config = pcm_config_hifi;
7878 }
7879
7880 out->config.rate = out->sample_rate;
7881 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7882 if (is_hdmi) {
7883 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7884 audio_bytes_per_sample(out->format));
7885 }
7886 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007887 }
7888
Derek Chenf6318be2017-06-12 17:16:24 -04007889 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007890 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007891 /* extract car audio stream index */
7892 out->car_audio_stream =
7893 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7894 if (out->car_audio_stream < 0) {
7895 ALOGE("%s: invalid car audio stream %x",
7896 __func__, out->car_audio_stream);
7897 ret = -EINVAL;
7898 goto error_open;
7899 }
Derek Chen5f67a942020-02-24 23:08:13 -08007900 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007901 }
7902
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007903 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007904 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007905 if (!voice_extn_is_compress_voip_supported()) {
7906 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7907 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007908 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307909 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007910 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7911 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007912 out->volume_l = INVALID_OUT_VOLUME;
7913 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007914
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007915 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007916 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007917 uint32_t channel_count =
7918 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307919 out->config.channels = channel_count;
7920
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007921 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7922 out->sample_rate, out->format,
7923 channel_count, false);
7924 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7925 if (frame_size != 0)
7926 out->config.period_size = buffer_size / frame_size;
7927 else
7928 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007929 }
7930 } else {
7931 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7932 voice_extn_compress_voip_is_active(out->dev)) &&
7933 (voice_extn_compress_voip_is_config_supported(config))) {
7934 ret = voice_extn_compress_voip_open_output_stream(out);
7935 if (ret != 0) {
7936 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7937 __func__, ret);
7938 goto error_open;
7939 }
Sujin Panicker19027262019-09-16 18:28:06 +05307940 } else {
7941 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7942 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007943 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007944 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007945 } else if (audio_is_linear_pcm(out->format) &&
7946 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7947 out->channel_mask = config->channel_mask;
7948 out->sample_rate = config->sample_rate;
7949 out->format = config->format;
7950 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7951 // does this change?
7952 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7953 out->config.rate = config->sample_rate;
7954 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7955 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7956 audio_bytes_per_sample(config->format));
7957 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007958 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307959 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307960 pthread_mutex_lock(&adev->lock);
7961 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7962 pthread_mutex_unlock(&adev->lock);
7963
7964 // reject offload during card offline to allow
7965 // fallback to s/w paths
7966 if (offline) {
7967 ret = -ENODEV;
7968 goto error_open;
7969 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007970
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007971 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7972 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7973 ALOGE("%s: Unsupported Offload information", __func__);
7974 ret = -EINVAL;
7975 goto error_open;
7976 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007977
Atul Khare3fa6e542017-08-09 00:56:17 +05307978 if (config->offload_info.format == 0)
7979 config->offload_info.format = config->format;
7980 if (config->offload_info.sample_rate == 0)
7981 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007982
Mingming Yin90310102013-11-13 16:57:00 -08007983 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307984 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007985 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007986 ret = -EINVAL;
7987 goto error_open;
7988 }
7989
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007990 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7991 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7992 (audio_extn_passthru_is_passthrough_stream(out)) &&
7993 !((config->sample_rate == 48000) ||
7994 (config->sample_rate == 96000) ||
7995 (config->sample_rate == 192000))) {
7996 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7997 __func__, config->sample_rate, config->offload_info.format);
7998 ret = -EINVAL;
7999 goto error_open;
8000 }
8001
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008002 out->compr_config.codec = (struct snd_codec *)
8003 calloc(1, sizeof(struct snd_codec));
8004
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008005 if (!out->compr_config.codec) {
8006 ret = -ENOMEM;
8007 goto error_open;
8008 }
8009
Dhananjay Kumarac341582017-02-23 23:42:25 +05308010 out->stream.pause = out_pause;
8011 out->stream.resume = out_resume;
8012 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308013 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308014 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008015 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308016 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008017 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308018 } else {
8019 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8020 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008021 }
vivek mehta446c3962015-09-14 10:57:35 -07008022
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308023 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8024 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008025#ifdef AUDIO_GKI_ENABLED
8026 /* out->compr_config.codec->reserved[1] is for flags */
8027 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8028#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308029 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008030#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308031 }
8032
vivek mehta446c3962015-09-14 10:57:35 -07008033 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008034 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008035 config->format == 0 && config->sample_rate == 0 &&
8036 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008037 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008038 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8039 } else {
8040 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8041 ret = -EEXIST;
8042 goto error_open;
8043 }
vivek mehta446c3962015-09-14 10:57:35 -07008044 }
8045
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008046 if (config->offload_info.channel_mask)
8047 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008048 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008049 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008050 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008051 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308052 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008053 ret = -EINVAL;
8054 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008055 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008056
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008057 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008058 out->sample_rate = config->offload_info.sample_rate;
8059
Mingming Yin3ee55c62014-08-04 14:23:35 -07008060 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008061
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308062 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308063 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308064 audio_extn_dolby_send_ddp_endp_params(adev);
8065 audio_extn_dolby_set_dmid(adev);
8066 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008067
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008068 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008069 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008070 out->compr_config.codec->bit_rate =
8071 config->offload_info.bit_rate;
8072 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308073 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008074 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308075 /* Update bit width only for non passthrough usecases.
8076 * For passthrough usecases, the output will always be opened @16 bit
8077 */
8078 if (!audio_extn_passthru_is_passthrough_stream(out))
8079 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308080
8081 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008082#ifdef AUDIO_GKI_ENABLED
8083 /* out->compr_config.codec->reserved[1] is for flags */
8084 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8085 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8086#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308087 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8088 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008089#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308090
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008091 /*TODO: Do we need to change it for passthrough */
8092 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008093
Manish Dewangana6fc5442015-08-24 20:30:31 +05308094 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8095 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308096 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308097 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308098 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8099 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308100
8101 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8102 AUDIO_FORMAT_PCM) {
8103
8104 /*Based on platform support, configure appropriate alsa format for corresponding
8105 *hal input format.
8106 */
8107 out->compr_config.codec->format = hal_format_to_alsa(
8108 config->offload_info.format);
8109
Ashish Jain83a6cc22016-06-28 14:34:17 +05308110 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308111 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308112 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308113
Dhananjay Kumarac341582017-02-23 23:42:25 +05308114 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308115 *hal input format and alsa format might differ based on platform support.
8116 */
8117 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308118 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308119
8120 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8121
Deeraj Soman93155a62019-09-30 19:00:37 +05308122 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8123 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8124 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8125 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8126 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308127
Ashish Jainf1eaa582016-05-23 20:54:24 +05308128 /* Check if alsa session is configured with the same format as HAL input format,
8129 * if not then derive correct fragment size needed to accomodate the
8130 * conversion of HAL input format to alsa format.
8131 */
8132 audio_extn_utils_update_direct_pcm_fragment_size(out);
8133
8134 /*if hal input and output fragment size is different this indicates HAL input format is
8135 *not same as the alsa format
8136 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308137 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308138 /*Allocate a buffer to convert input data to the alsa configured format.
8139 *size of convert buffer is equal to the size required to hold one fragment size
8140 *worth of pcm data, this is because flinger does not write more than fragment_size
8141 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308142 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8143 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308144 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8145 ret = -ENOMEM;
8146 goto error_open;
8147 }
8148 }
8149 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8150 out->compr_config.fragment_size =
8151 audio_extn_passthru_get_buffer_size(&config->offload_info);
8152 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8153 } else {
8154 out->compr_config.fragment_size =
8155 platform_get_compress_offload_buffer_size(&config->offload_info);
8156 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8157 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008158
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308159 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8160 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8161 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008162 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8163#ifdef AUDIO_GKI_ENABLED
8164 generic_dec =
8165 &(out->compr_config.codec->options.generic.reserved[1]);
8166 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8167 AUDIO_OUTPUT_BIT_WIDTH;
8168#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308169 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008170#endif
8171 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008172
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308173 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8174 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8175 }
8176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008177 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8178 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008179
Manish Dewangan69426c82017-01-30 17:35:36 +05308180 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8181 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8182 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8183 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8184 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8185 } else {
8186 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8187 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008188
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308189 memset(&out->channel_map_param, 0,
8190 sizeof(struct audio_out_channel_map_param));
8191
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008192 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308193 out->send_next_track_params = false;
8194 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008195 out->offload_state = OFFLOAD_STATE_IDLE;
8196 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008197 out->writeAt.tv_sec = 0;
8198 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008199
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008200 audio_extn_dts_create_state_notifier_node(out->usecase);
8201
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008202 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8203 __func__, config->offload_info.version,
8204 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308205
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308206 /* Check if DSD audio format is supported in codec
8207 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308208 */
8209
8210 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308211 (!platform_check_codec_dsd_support(adev->platform) ||
8212 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308213 ret = -EINVAL;
8214 goto error_open;
8215 }
8216
Ashish Jain5106d362016-05-11 19:23:33 +05308217 /* Disable gapless if any of the following is true
8218 * passthrough playback
8219 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308220 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308221 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308222 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308223 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008224 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308225 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308226 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308227 check_and_set_gapless_mode(adev, false);
8228 } else
8229 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008230
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308231 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008232 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8233 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308234 if (config->format == AUDIO_FORMAT_DSD) {
8235 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008236#ifdef AUDIO_GKI_ENABLED
8237 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8238 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8239#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308240 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008241#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308242 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008243
8244 create_offload_callback_thread(out);
8245
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008246 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008247 switch (config->sample_rate) {
8248 case 0:
8249 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8250 break;
8251 case 8000:
8252 case 16000:
8253 case 48000:
8254 out->sample_rate = config->sample_rate;
8255 break;
8256 default:
8257 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8258 config->sample_rate);
8259 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8260 ret = -EINVAL;
8261 goto error_open;
8262 }
8263 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8264 switch (config->channel_mask) {
8265 case AUDIO_CHANNEL_NONE:
8266 case AUDIO_CHANNEL_OUT_STEREO:
8267 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8268 break;
8269 default:
8270 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8271 config->channel_mask);
8272 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8273 ret = -EINVAL;
8274 goto error_open;
8275 }
8276 switch (config->format) {
8277 case AUDIO_FORMAT_DEFAULT:
8278 case AUDIO_FORMAT_PCM_16_BIT:
8279 out->format = AUDIO_FORMAT_PCM_16_BIT;
8280 break;
8281 default:
8282 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8283 config->format);
8284 config->format = AUDIO_FORMAT_PCM_16_BIT;
8285 ret = -EINVAL;
8286 goto error_open;
8287 }
8288
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308289 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008290 if (ret != 0) {
8291 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008292 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008293 goto error_open;
8294 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008295 } else if (is_single_device_type_equal(&out->device_list,
8296 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008297 switch (config->sample_rate) {
8298 case 0:
8299 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8300 break;
8301 case 8000:
8302 case 16000:
8303 case 48000:
8304 out->sample_rate = config->sample_rate;
8305 break;
8306 default:
8307 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8308 config->sample_rate);
8309 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8310 ret = -EINVAL;
8311 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008312 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008313 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8314 switch (config->channel_mask) {
8315 case AUDIO_CHANNEL_NONE:
8316 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8317 break;
8318 case AUDIO_CHANNEL_OUT_STEREO:
8319 out->channel_mask = config->channel_mask;
8320 break;
8321 default:
8322 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8323 config->channel_mask);
8324 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8325 ret = -EINVAL;
8326 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008327 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008328 switch (config->format) {
8329 case AUDIO_FORMAT_DEFAULT:
8330 out->format = AUDIO_FORMAT_PCM_16_BIT;
8331 break;
8332 case AUDIO_FORMAT_PCM_16_BIT:
8333 out->format = config->format;
8334 break;
8335 default:
8336 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8337 config->format);
8338 config->format = AUDIO_FORMAT_PCM_16_BIT;
8339 ret = -EINVAL;
8340 break;
8341 }
8342 if (ret != 0)
8343 goto error_open;
8344
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008345 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8346 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008347 out->config.rate = out->sample_rate;
8348 out->config.channels =
8349 audio_channel_count_from_out_mask(out->channel_mask);
8350 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008351 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008352 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308353 unsigned int channels = 0;
8354 /*Update config params to default if not set by the caller*/
8355 if (config->sample_rate == 0)
8356 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8357 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8358 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8359 if (config->format == AUDIO_FORMAT_DEFAULT)
8360 config->format = AUDIO_FORMAT_PCM_16_BIT;
8361
8362 channels = audio_channel_count_from_out_mask(out->channel_mask);
8363
Varun Balaraje49253e2017-07-06 19:48:56 +05308364 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8365 out->usecase = get_interactive_usecase(adev);
8366 out->config = pcm_config_low_latency;
8367 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308368 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008369 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8370 out->flags);
8371 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008372 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8373 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8374 out->config = pcm_config_mmap_playback;
8375 out->stream.start = out_start;
8376 out->stream.stop = out_stop;
8377 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8378 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308379 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8380 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008381 out->hal_output_suspend_supported =
8382 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8383 out->dynamic_pm_qos_config_supported =
8384 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8385 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008386 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8387 } else {
8388 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8389 //the mixer path will be a string similar to "low-latency-playback resume"
8390 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8391 strlcat(out->pm_qos_mixer_path,
8392 " resume", MAX_MIXER_PATH_LEN);
8393 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8394 out->pm_qos_mixer_path);
8395 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308396 out->config = pcm_config_low_latency;
8397 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8398 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8399 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308400 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8401 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8402 if (out->config.period_size <= 0) {
8403 ALOGE("Invalid configuration period size is not valid");
8404 ret = -EINVAL;
8405 goto error_open;
8406 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008407 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8408 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8409 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008410 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8411 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8412 out->config = pcm_config_haptics_audio;
8413 if (force_haptic_path)
8414 adev->haptics_config = pcm_config_haptics_audio;
8415 else
8416 adev->haptics_config = pcm_config_haptics;
8417
Meng Wangd08ce322020-04-02 08:59:20 +08008418 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008419 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8420
8421 if (force_haptic_path) {
8422 out->config.channels = 1;
8423 adev->haptics_config.channels = 1;
8424 } else
8425 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 -08008426 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008427 ret = audio_extn_auto_hal_open_output_stream(out);
8428 if (ret) {
8429 ALOGE("%s: Failed to open output stream for bus device", __func__);
8430 ret = -EINVAL;
8431 goto error_open;
8432 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308433 } else {
8434 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008435 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8436 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308437 }
8438 out->hal_ip_format = format = out->format;
8439 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8440 out->hal_op_format = pcm_format_to_hal(out->config.format);
8441 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8442 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008443 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308444 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308445 if (out->hal_ip_format != out->hal_op_format) {
8446 uint32_t buffer_size = out->config.period_size *
8447 format_to_bitwidth_table[out->hal_op_format] *
8448 out->config.channels;
8449 out->convert_buffer = calloc(1, buffer_size);
8450 if (out->convert_buffer == NULL){
8451 ALOGE("Allocation failed for convert buffer for size %d",
8452 out->compr_config.fragment_size);
8453 ret = -ENOMEM;
8454 goto error_open;
8455 }
8456 ALOGD("Convert buffer allocated of size %d", buffer_size);
8457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008458 }
8459
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008460 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8461 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308462
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008463 /* TODO remove this hardcoding and check why width is zero*/
8464 if (out->bit_width == 0)
8465 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308466 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008467 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008468 &out->device_list, out->flags,
8469 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308470 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308471 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008472 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008473 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8474 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008475 if(adev->primary_output == NULL)
8476 adev->primary_output = out;
8477 else {
8478 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008479 ret = -EEXIST;
8480 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008481 }
8482 }
8483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008484 /* Check if this usecase is already existing */
8485 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008486 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8487 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008488 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008489 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008490 ret = -EEXIST;
8491 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008492 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008494 pthread_mutex_unlock(&adev->lock);
8495
8496 out->stream.common.get_sample_rate = out_get_sample_rate;
8497 out->stream.common.set_sample_rate = out_set_sample_rate;
8498 out->stream.common.get_buffer_size = out_get_buffer_size;
8499 out->stream.common.get_channels = out_get_channels;
8500 out->stream.common.get_format = out_get_format;
8501 out->stream.common.set_format = out_set_format;
8502 out->stream.common.standby = out_standby;
8503 out->stream.common.dump = out_dump;
8504 out->stream.common.set_parameters = out_set_parameters;
8505 out->stream.common.get_parameters = out_get_parameters;
8506 out->stream.common.add_audio_effect = out_add_audio_effect;
8507 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8508 out->stream.get_latency = out_get_latency;
8509 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008510#ifdef NO_AUDIO_OUT
8511 out->stream.write = out_write_for_no_output;
8512#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008513 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008514#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008515 out->stream.get_render_position = out_get_render_position;
8516 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008517 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518
Haynes Mathew George16081042017-05-31 17:16:49 -07008519 if (out->realtime)
8520 out->af_period_multiplier = af_period_multiplier;
8521 else
8522 out->af_period_multiplier = 1;
8523
Andy Hunga1f48fa2019-07-01 18:14:53 -07008524 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008526 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008527 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008528 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529
8530 config->format = out->stream.common.get_format(&out->stream.common);
8531 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8532 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308533 register_format(out->format, out->supported_formats);
8534 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8535 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008536
Aalique Grahame22e49102018-12-18 14:23:57 -08008537 out->error_log = error_log_create(
8538 ERROR_LOG_ENTRIES,
8539 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8540
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308541 /*
8542 By locking output stream before registering, we allow the callback
8543 to update stream's state only after stream's initial state is set to
8544 adev state.
8545 */
8546 lock_output_stream(out);
8547 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8548 pthread_mutex_lock(&adev->lock);
8549 out->card_status = adev->card_status;
8550 pthread_mutex_unlock(&adev->lock);
8551 pthread_mutex_unlock(&out->lock);
8552
Aalique Grahame22e49102018-12-18 14:23:57 -08008553 stream_app_type_cfg_init(&out->app_type_cfg);
8554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008555 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308556 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008557 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008558
8559 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8560 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8561 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008562 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308563 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008564 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008565 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308566 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8567 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008568 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8569 out->usecase, PCM_PLAYBACK);
8570 hdlr_stream_cfg.flags = out->flags;
8571 hdlr_stream_cfg.type = PCM_PLAYBACK;
8572 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8573 &hdlr_stream_cfg);
8574 if (ret) {
8575 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8576 out->adsp_hdlr_stream_handle = NULL;
8577 }
8578 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308579 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8580 is_direct_passthough, false);
8581 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8582 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008583 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008584 if (ret < 0) {
8585 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8586 out->ip_hdlr_handle = NULL;
8587 }
8588 }
Derek Chenf939fb72018-11-13 13:34:41 -08008589
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008590 ret = io_streams_map_insert(adev, &out->stream.common,
8591 out->handle, AUDIO_PATCH_HANDLE_NONE);
8592 if (ret != 0)
8593 goto error_open;
8594
Derek Chenf939fb72018-11-13 13:34:41 -08008595 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8596 calloc(1, sizeof(streams_output_ctxt_t));
8597 if (out_ctxt == NULL) {
8598 ALOGE("%s fail to allocate output ctxt", __func__);
8599 ret = -ENOMEM;
8600 goto error_open;
8601 }
8602 out_ctxt->output = out;
8603
8604 pthread_mutex_lock(&adev->lock);
8605 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8606 pthread_mutex_unlock(&adev->lock);
8607
Eric Laurent994a6932013-07-17 11:51:42 -07008608 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008609 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008610
8611error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308612 if (out->convert_buffer)
8613 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008614 free(out);
8615 *stream_out = NULL;
8616 ALOGD("%s: exit: ret %d", __func__, ret);
8617 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008618}
8619
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308620void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008621 struct audio_stream_out *stream)
8622{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008623 struct stream_out *out = (struct stream_out *)stream;
8624 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008625 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008626
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008627 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308628
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008629 io_streams_map_remove(adev, out->handle);
8630
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308631 // must deregister from sndmonitor first to prevent races
8632 // between the callback and close_stream
8633 audio_extn_snd_mon_unregister_listener(out);
8634
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008635 /* close adsp hdrl session before standby */
8636 if (out->adsp_hdlr_stream_handle) {
8637 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8638 if (ret)
8639 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8640 out->adsp_hdlr_stream_handle = NULL;
8641 }
8642
Manish Dewangan21a850a2017-08-14 12:03:55 +05308643 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008644 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8645 out->ip_hdlr_handle = NULL;
8646 }
8647
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008648 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308649 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008650 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308651 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308652 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008653 if(ret != 0)
8654 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8655 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008656 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008657 out_standby(&stream->common);
8658
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008659 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008660 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008661 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008662 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008663 if (out->compr_config.codec != NULL)
8664 free(out->compr_config.codec);
8665 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008666
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308667 out->a2dp_compress_mute = false;
8668
Varun Balaraje49253e2017-07-06 19:48:56 +05308669 if (is_interactive_usecase(out->usecase))
8670 free_interactive_usecase(adev, out->usecase);
8671
Ashish Jain83a6cc22016-06-28 14:34:17 +05308672 if (out->convert_buffer != NULL) {
8673 free(out->convert_buffer);
8674 out->convert_buffer = NULL;
8675 }
8676
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008677 if (adev->voice_tx_output == out)
8678 adev->voice_tx_output = NULL;
8679
Aalique Grahame22e49102018-12-18 14:23:57 -08008680 error_log_destroy(out->error_log);
8681 out->error_log = NULL;
8682
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308683 if (adev->primary_output == out)
8684 adev->primary_output = NULL;
8685
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008686 pthread_cond_destroy(&out->cond);
8687 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008688 pthread_mutex_destroy(&out->pre_lock);
8689 pthread_mutex_destroy(&out->latch_lock);
8690 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008691
8692 pthread_mutex_lock(&adev->lock);
8693 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8694 if (out_ctxt != NULL) {
8695 list_remove(&out_ctxt->list);
8696 free(out_ctxt);
8697 } else {
8698 ALOGW("%s, output stream already closed", __func__);
8699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008700 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008701 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008702 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008703}
8704
8705static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8706{
8707 struct audio_device *adev = (struct audio_device *)dev;
8708 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008709 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008710 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008711 int ret;
8712 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008713 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008714 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008715 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008716
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008717 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008718 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008719
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308720 if (!parms)
8721 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308722
Derek Chen6f293672019-04-01 01:40:24 -07008723 /* notify adev and input/output streams on the snd card status */
8724 adev_snd_mon_cb((void *)adev, parms);
8725
8726 list_for_each(node, &adev->active_outputs_list) {
8727 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8728 streams_output_ctxt_t,
8729 list);
8730 out_snd_mon_cb((void *)out_ctxt->output, parms);
8731 }
8732
8733 list_for_each(node, &adev->active_inputs_list) {
8734 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8735 streams_input_ctxt_t,
8736 list);
8737 in_snd_mon_cb((void *)in_ctxt->input, parms);
8738 }
8739
Zhou Songd6d71752019-05-21 18:08:51 +08008740 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308741 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8742 if (ret >= 0) {
8743 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008744 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308745 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008746 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308747 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008748 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008749 }
8750 }
8751
8752 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008753 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008754 if (!strncmp(value, "false", 5) &&
8755 audio_extn_a2dp_source_is_suspended()) {
8756 struct audio_usecase *usecase;
8757 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008758 list_for_each(node, &adev->usecase_list) {
8759 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008760 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008761 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008762 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008763 reassign_device_list(&usecase->stream.in->device_list,
8764 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008765 select_devices(adev, usecase->id);
8766 }
Zhou Songd6d71752019-05-21 18:08:51 +08008767 }
8768 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308769 }
8770
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008771 status = voice_set_parameters(adev, parms);
8772 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008773 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008774
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008775 status = platform_set_parameters(adev->platform, parms);
8776 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008777 goto done;
8778
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008779 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8780 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008781 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8783 adev->bluetooth_nrec = true;
8784 else
8785 adev->bluetooth_nrec = false;
8786 }
8787
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008788 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8789 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008790 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8791 adev->screen_off = false;
8792 else
8793 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008794 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008795 }
8796
Eric Laurent4b084132018-10-19 17:33:43 -07008797 ret = str_parms_get_int(parms, "rotation", &val);
8798 if (ret >= 0) {
8799 bool reverse_speakers = false;
8800 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8801 switch (val) {
8802 // FIXME: note that the code below assumes that the speakers are in the correct placement
8803 // relative to the user when the device is rotated 90deg from its default rotation. This
8804 // assumption is device-specific, not platform-specific like this code.
8805 case 270:
8806 reverse_speakers = true;
8807 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8808 break;
8809 case 0:
8810 case 180:
8811 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8812 break;
8813 case 90:
8814 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8815 break;
8816 default:
8817 ALOGE("%s: unexpected rotation of %d", __func__, val);
8818 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008819 }
Eric Laurent4b084132018-10-19 17:33:43 -07008820 if (status == 0) {
8821 // check and set swap
8822 // - check if orientation changed and speaker active
8823 // - set rotation and cache the rotation value
8824 adev->camera_orientation =
8825 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8826 if (!audio_extn_is_maxx_audio_enabled())
8827 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8828 }
8829 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008830
Mingming Yin514a8bc2014-07-29 15:22:21 -07008831 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8832 if (ret >= 0) {
8833 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8834 adev->bt_wb_speech_enabled = true;
8835 else
8836 adev->bt_wb_speech_enabled = false;
8837 }
8838
Zhou Song12c29502019-03-16 10:37:18 +08008839 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8840 if (ret >= 0) {
8841 val = atoi(value);
8842 adev->swb_speech_mode = val;
8843 }
8844
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008845 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8846 if (ret >= 0) {
8847 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308848 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008849 if (audio_is_output_device(val) &&
8850 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008851 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008852 platform_get_controller_stream_from_params(parms, &controller, &stream);
8853 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8854 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008855 if (ret < 0) {
8856 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308857 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008858 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008859 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308860 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008861 /*
8862 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8863 * Per AudioPolicyManager, USB device is higher priority than WFD.
8864 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8865 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8866 * starting voice call on USB
8867 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008868 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308869 if (ret >= 0)
8870 audio_extn_usb_add_device(device, atoi(value));
8871
Zhou Song6f862822017-11-06 17:27:57 +08008872 if (!audio_extn_usb_is_tunnel_supported()) {
8873 ALOGV("detected USB connect .. disable proxy");
8874 adev->allow_afe_proxy_usage = false;
8875 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008876 }
8877 }
8878
8879 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8880 if (ret >= 0) {
8881 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308882 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008883 /*
8884 * The HDMI / Displayport disconnect handling has been moved to
8885 * audio extension to ensure that its parameters are not
8886 * invalidated prior to updating sysfs of the disconnect event
8887 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8888 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308889 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008890 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308891 if (ret >= 0)
8892 audio_extn_usb_remove_device(device, atoi(value));
8893
Zhou Song6f862822017-11-06 17:27:57 +08008894 if (!audio_extn_usb_is_tunnel_supported()) {
8895 ALOGV("detected USB disconnect .. enable proxy");
8896 adev->allow_afe_proxy_usage = true;
8897 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008898 }
8899 }
8900
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008901 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008902
8903 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008904 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308905 struct audio_usecase *usecase;
8906 struct listnode *node;
8907 list_for_each(node, &adev->usecase_list) {
8908 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008909 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8910 continue;
8911
8912 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308913 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308914 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308915 ALOGD("Switching to speaker and muting the stream before select_devices");
8916 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308917 //force device switch to re configure encoder
8918 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308919 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008920 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308921 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008922 out_set_compr_volume(&usecase->stream.out->stream,
8923 usecase->stream.out->volume_l,
8924 usecase->stream.out->volume_r);
8925 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308926 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308927 break;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008928 } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
8929 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8930 if (usecase->stream.out->a2dp_compress_mute) {
8931 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8932 reassign_device_list(&usecase->stream.out->device_list,
8933 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8934 check_a2dp_restore_l(adev, usecase->stream.out, true);
8935 break;
8936 }
8937 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308938 }
8939 }
8940 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008941
8942 //handle vr audio setparam
8943 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8944 value, sizeof(value));
8945 if (ret >= 0) {
8946 ALOGI("Setting vr mode to be %s", value);
8947 if (!strncmp(value, "true", 4)) {
8948 adev->vr_audio_mode_enabled = true;
8949 ALOGI("Setting vr mode to true");
8950 } else if (!strncmp(value, "false", 5)) {
8951 adev->vr_audio_mode_enabled = false;
8952 ALOGI("Setting vr mode to false");
8953 } else {
8954 ALOGI("wrong vr mode set");
8955 }
8956 }
8957
Eric Laurent4b084132018-10-19 17:33:43 -07008958 //FIXME: to be replaced by proper video capture properties API
8959 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8960 if (ret >= 0) {
8961 int camera_facing = CAMERA_FACING_BACK;
8962 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8963 camera_facing = CAMERA_FACING_FRONT;
8964 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8965 camera_facing = CAMERA_FACING_BACK;
8966 else {
8967 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8968 goto done;
8969 }
8970 adev->camera_orientation =
8971 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8972 struct audio_usecase *usecase;
8973 struct listnode *node;
8974 list_for_each(node, &adev->usecase_list) {
8975 usecase = node_to_item(node, struct audio_usecase, list);
8976 struct stream_in *in = usecase->stream.in;
8977 if (usecase->type == PCM_CAPTURE && in != NULL &&
8978 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8979 select_devices(adev, in->usecase);
8980 }
8981 }
8982 }
8983
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308984 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008985done:
8986 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008987 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308988error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008989 ALOGV("%s: exit with code(%d)", __func__, status);
8990 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008991}
8992
8993static char* adev_get_parameters(const struct audio_hw_device *dev,
8994 const char *keys)
8995{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308996 ALOGD("%s:%s", __func__, keys);
8997
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008998 struct audio_device *adev = (struct audio_device *)dev;
8999 struct str_parms *reply = str_parms_create();
9000 struct str_parms *query = str_parms_create_str(keys);
9001 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309002 char value[256] = {0};
9003 int ret = 0;
9004
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009005 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009006 if (reply) {
9007 str_parms_destroy(reply);
9008 }
9009 if (query) {
9010 str_parms_destroy(query);
9011 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009012 ALOGE("adev_get_parameters: failed to create query or reply");
9013 return NULL;
9014 }
9015
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009016 //handle vr audio getparam
9017
9018 ret = str_parms_get_str(query,
9019 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9020 value, sizeof(value));
9021
9022 if (ret >= 0) {
9023 bool vr_audio_enabled = false;
9024 pthread_mutex_lock(&adev->lock);
9025 vr_audio_enabled = adev->vr_audio_mode_enabled;
9026 pthread_mutex_unlock(&adev->lock);
9027
9028 ALOGI("getting vr mode to %d", vr_audio_enabled);
9029
9030 if (vr_audio_enabled) {
9031 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9032 "true");
9033 goto exit;
9034 } else {
9035 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9036 "false");
9037 goto exit;
9038 }
9039 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009040
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009041 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009042 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009043 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009044 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009045 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009046 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309047 pthread_mutex_unlock(&adev->lock);
9048
Naresh Tannirud7205b62014-06-20 02:54:48 +05309049exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009050 str = str_parms_to_str(reply);
9051 str_parms_destroy(query);
9052 str_parms_destroy(reply);
9053
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309054 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009055 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009056}
9057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009058static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009059{
9060 return 0;
9061}
9062
9063static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9064{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009065 int ret;
9066 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009067
9068 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9069
Haynes Mathew George5191a852013-09-11 14:19:36 -07009070 pthread_mutex_lock(&adev->lock);
9071 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009072 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009073 pthread_mutex_unlock(&adev->lock);
9074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009075}
9076
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009077static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9078 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009079{
9080 return -ENOSYS;
9081}
9082
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009083static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9084 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009085{
9086 return -ENOSYS;
9087}
9088
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009089static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9090 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009091{
9092 return -ENOSYS;
9093}
9094
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009095static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9096 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009097{
9098 return -ENOSYS;
9099}
9100
9101static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9102{
9103 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009104 struct listnode *node;
9105 struct audio_usecase *usecase = NULL;
9106 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009108 pthread_mutex_lock(&adev->lock);
9109 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309110 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9111 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009113 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309114 adev->current_call_output = adev->primary_output;
9115 voice_start_call(adev);
9116 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009117 (mode == AUDIO_MODE_NORMAL ||
9118 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009119 list_for_each(node, &adev->usecase_list) {
9120 usecase = node_to_item(node, struct audio_usecase, list);
9121 if (usecase->type == VOICE_CALL)
9122 break;
9123 }
9124 if (usecase &&
9125 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9126 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9127 true);
9128 if (ret != 0) {
9129 /* default service interval was successfully updated,
9130 reopen USB backend with new service interval */
9131 check_usecases_codec_backend(adev,
9132 usecase,
9133 usecase->out_snd_device);
9134 }
9135 }
9136
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009137 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009138 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009139 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009140 // restore device for other active usecases after stop call
9141 list_for_each(node, &adev->usecase_list) {
9142 usecase = node_to_item(node, struct audio_usecase, list);
9143 select_devices(adev, usecase->id);
9144 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009145 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009146 }
9147 pthread_mutex_unlock(&adev->lock);
9148 return 0;
9149}
9150
9151static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9152{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009153 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009154 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009155
9156 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009157 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009158 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009159
Derek Chend2530072014-11-24 12:39:14 -08009160 if (adev->ext_hw_plugin)
9161 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009162
9163 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009164 pthread_mutex_unlock(&adev->lock);
9165
9166 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009167}
9168
9169static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9170{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009171 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172 return 0;
9173}
9174
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009175static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176 const struct audio_config *config)
9177{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009178 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009179
Aalique Grahame22e49102018-12-18 14:23:57 -08009180 /* Don't know if USB HIFI in this context so use true to be conservative */
9181 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9182 true /*is_usb_hifi */) != 0)
9183 return 0;
9184
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009185 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9186 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009187}
9188
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009189static bool adev_input_allow_hifi_record(struct audio_device *adev,
9190 audio_devices_t devices,
9191 audio_input_flags_t flags,
9192 audio_source_t source) {
9193 const bool allowed = true;
9194
9195 if (!audio_is_usb_in_device(devices))
9196 return !allowed;
9197
9198 switch (flags) {
9199 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009200 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009201 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9202 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009203 default:
9204 return !allowed;
9205 }
9206
9207 switch (source) {
9208 case AUDIO_SOURCE_DEFAULT:
9209 case AUDIO_SOURCE_MIC:
9210 case AUDIO_SOURCE_UNPROCESSED:
9211 break;
9212 default:
9213 return !allowed;
9214 }
9215
9216 switch (adev->mode) {
9217 case 0:
9218 break;
9219 default:
9220 return !allowed;
9221 }
9222
9223 return allowed;
9224}
9225
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009226static int adev_update_voice_comm_input_stream(struct stream_in *in,
9227 struct audio_config *config)
9228{
9229 bool valid_rate = (config->sample_rate == 8000 ||
9230 config->sample_rate == 16000 ||
9231 config->sample_rate == 32000 ||
9232 config->sample_rate == 48000);
9233 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9234
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009235 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009236 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009237 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9238 in->config = default_pcm_config_voip_copp;
9239 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9240 DEFAULT_VOIP_BUF_DURATION_MS,
9241 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009242 } else {
9243 ALOGW("%s No valid input in voip, use defaults"
9244 "sample rate %u, channel mask 0x%X",
9245 __func__, config->sample_rate, in->channel_mask);
9246 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009247 in->config.rate = config->sample_rate;
9248 in->sample_rate = config->sample_rate;
9249 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009250 //XXX needed for voice_extn_compress_voip_open_input_stream
9251 in->config.rate = config->sample_rate;
9252 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309253 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009254 voice_extn_compress_voip_is_active(in->dev)) &&
9255 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9256 valid_rate && valid_ch) {
9257 voice_extn_compress_voip_open_input_stream(in);
9258 // update rate entries to match config from AF
9259 in->config.rate = config->sample_rate;
9260 in->sample_rate = config->sample_rate;
9261 } else {
9262 ALOGW("%s compress voip not active, use defaults", __func__);
9263 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009264 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009265 return 0;
9266}
9267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009268static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009269 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009270 audio_devices_t devices,
9271 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009272 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309273 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009274 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009275 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009276{
9277 struct audio_device *adev = (struct audio_device *)dev;
9278 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009279 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009280 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009281 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309282 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009283 bool is_usb_dev = audio_is_usb_in_device(devices);
9284 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9285 devices,
9286 flags,
9287 source);
Andy Hung94320602018-10-29 18:31:12 -07009288 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9289 " sample_rate %u, channel_mask %#x, format %#x",
9290 __func__, flags, is_usb_dev, may_use_hifi_record,
9291 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309292
kunleizdff872d2018-08-20 14:40:33 +08009293 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009294 is_usb_dev = false;
9295 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9296 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9297 __func__, devices);
9298 }
9299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009300 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009301
9302 if (!(is_usb_dev && may_use_hifi_record)) {
9303 if (config->sample_rate == 0)
9304 config->sample_rate = 48000;
9305 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9306 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9307 if (config->format == AUDIO_FORMAT_DEFAULT)
9308 config->format = AUDIO_FORMAT_PCM_16_BIT;
9309
9310 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9311
Aalique Grahame22e49102018-12-18 14:23:57 -08009312 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9313 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009314 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009316
Rahul Sharma99770982019-03-06 17:05:26 +05309317 pthread_mutex_lock(&adev->lock);
9318 if (in_get_stream(adev, handle) != NULL) {
9319 ALOGW("%s, input stream already opened", __func__);
9320 ret = -EEXIST;
9321 }
9322 pthread_mutex_unlock(&adev->lock);
9323 if (ret)
9324 return ret;
9325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009326 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009327
9328 if (!in) {
9329 ALOGE("failed to allocate input stream");
9330 return -ENOMEM;
9331 }
9332
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309333 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309334 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9335 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009336 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009337 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009339 in->stream.common.get_sample_rate = in_get_sample_rate;
9340 in->stream.common.set_sample_rate = in_set_sample_rate;
9341 in->stream.common.get_buffer_size = in_get_buffer_size;
9342 in->stream.common.get_channels = in_get_channels;
9343 in->stream.common.get_format = in_get_format;
9344 in->stream.common.set_format = in_set_format;
9345 in->stream.common.standby = in_standby;
9346 in->stream.common.dump = in_dump;
9347 in->stream.common.set_parameters = in_set_parameters;
9348 in->stream.common.get_parameters = in_get_parameters;
9349 in->stream.common.add_audio_effect = in_add_audio_effect;
9350 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9351 in->stream.set_gain = in_set_gain;
9352 in->stream.read = in_read;
9353 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009354 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309355 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009356 in->stream.set_microphone_direction = in_set_microphone_direction;
9357 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009358 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009359
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009360 list_init(&in->device_list);
9361 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009362 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009363 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009364 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009365 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009366 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009367 in->bit_width = 16;
9368 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009369 in->direction = MIC_DIRECTION_UNSPECIFIED;
9370 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009371 list_init(&in->aec_list);
9372 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009373 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009374
Andy Hung94320602018-10-29 18:31:12 -07009375 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009376 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9377 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9378 /* Force channel config requested to mono if incall
9379 record is being requested for only uplink/downlink */
9380 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9381 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9382 ret = -EINVAL;
9383 goto err_open;
9384 }
9385 }
9386
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009387 if (is_usb_dev && may_use_hifi_record) {
9388 /* HiFi record selects an appropriate format, channel, rate combo
9389 depending on sink capabilities*/
9390 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9391 &config->format,
9392 &in->supported_formats[0],
9393 MAX_SUPPORTED_FORMATS,
9394 &config->channel_mask,
9395 &in->supported_channel_masks[0],
9396 MAX_SUPPORTED_CHANNEL_MASKS,
9397 &config->sample_rate,
9398 &in->supported_sample_rates[0],
9399 MAX_SUPPORTED_SAMPLE_RATES);
9400 if (ret != 0) {
9401 ret = -EINVAL;
9402 goto err_open;
9403 }
9404 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009405 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309406 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309407 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9408 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9409 in->config.format = PCM_FORMAT_S32_LE;
9410 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309411 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9412 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9413 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9414 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9415 bool ret_error = false;
9416 in->bit_width = 24;
9417 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9418 from HAL is 24_packed and 8_24
9419 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9420 24_packed return error indicating supported format is 24_packed
9421 *> In case of any other source requesting 24 bit or float return error
9422 indicating format supported is 16 bit only.
9423
9424 on error flinger will retry with supported format passed
9425 */
9426 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9427 (source != AUDIO_SOURCE_CAMCORDER)) {
9428 config->format = AUDIO_FORMAT_PCM_16_BIT;
9429 if (config->sample_rate > 48000)
9430 config->sample_rate = 48000;
9431 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009432 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9433 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309434 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9435 ret_error = true;
9436 }
9437
9438 if (ret_error) {
9439 ret = -EINVAL;
9440 goto err_open;
9441 }
9442 }
9443
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009444 in->channel_mask = config->channel_mask;
9445 in->format = config->format;
9446
9447 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309448
9449 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9450 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9451 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9452 else {
9453 ret = -EINVAL;
9454 goto err_open;
9455 }
9456 }
9457
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009458 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309459 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9460 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009461 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9462 is_low_latency = true;
9463#if LOW_LATENCY_CAPTURE_USE_CASE
9464 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9465#endif
9466 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009467 if (!in->realtime) {
9468 in->config = pcm_config_audio_capture;
9469 frame_size = audio_stream_in_frame_size(&in->stream);
9470 buffer_size = get_input_buffer_size(config->sample_rate,
9471 config->format,
9472 channel_count,
9473 is_low_latency);
9474 in->config.period_size = buffer_size / frame_size;
9475 in->config.rate = config->sample_rate;
9476 in->af_period_multiplier = 1;
9477 } else {
9478 // period size is left untouched for rt mode playback
9479 in->config = pcm_config_audio_capture_rt;
9480 in->af_period_multiplier = af_period_multiplier;
9481 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009482 }
9483
9484 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9485 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9486 in->realtime = 0;
9487 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9488 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009489 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009490 in->stream.start = in_start;
9491 in->stream.stop = in_stop;
9492 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9493 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009494 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009495 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009496 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9497 in->config = pcm_config_audio_capture;
9498 frame_size = audio_stream_in_frame_size(&in->stream);
9499 buffer_size = get_input_buffer_size(config->sample_rate,
9500 config->format,
9501 channel_count,
9502 false /*is_low_latency*/);
9503 in->config.period_size = buffer_size / frame_size;
9504 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009505 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009506 switch (config->format) {
9507 case AUDIO_FORMAT_PCM_32_BIT:
9508 in->bit_width = 32;
9509 break;
9510 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9511 case AUDIO_FORMAT_PCM_8_24_BIT:
9512 in->bit_width = 24;
9513 break;
9514 default:
9515 in->bit_width = 16;
9516 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009517 } else if (is_single_device_type_equal(&in->device_list,
9518 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9519 is_single_device_type_equal(&in->device_list,
9520 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009521 if (config->sample_rate == 0)
9522 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9523 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9524 config->sample_rate != 8000) {
9525 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9526 ret = -EINVAL;
9527 goto err_open;
9528 }
9529 if (config->format == AUDIO_FORMAT_DEFAULT)
9530 config->format = AUDIO_FORMAT_PCM_16_BIT;
9531 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9532 config->format = AUDIO_FORMAT_PCM_16_BIT;
9533 ret = -EINVAL;
9534 goto err_open;
9535 }
9536
9537 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009538 if (adev->ha_proxy_enable &&
9539 is_single_device_type_equal(&in->device_list,
9540 AUDIO_DEVICE_IN_TELEPHONY_RX))
9541 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009542 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009543 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009544 in->af_period_multiplier = 1;
9545 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9546 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9547 (config->sample_rate == 8000 ||
9548 config->sample_rate == 16000 ||
9549 config->sample_rate == 32000 ||
9550 config->sample_rate == 48000) &&
9551 channel_count == 1) {
9552 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9553 in->config = pcm_config_audio_capture;
9554 frame_size = audio_stream_in_frame_size(&in->stream);
9555 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9556 config->sample_rate,
9557 config->format,
9558 channel_count, false /*is_low_latency*/);
9559 in->config.period_size = buffer_size / frame_size;
9560 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9561 in->config.rate = config->sample_rate;
9562 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009563 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309564 int ret_val;
9565 pthread_mutex_lock(&adev->lock);
9566 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9567 in, config, &channel_mask_updated);
9568 pthread_mutex_unlock(&adev->lock);
9569
9570 if (!ret_val) {
9571 if (channel_mask_updated == true) {
9572 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9573 __func__, config->channel_mask);
9574 ret = -EINVAL;
9575 goto err_open;
9576 }
9577 ALOGD("%s: created multi-channel session succesfully",__func__);
9578 } else if (audio_extn_compr_cap_enabled() &&
9579 audio_extn_compr_cap_format_supported(config->format) &&
9580 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9581 audio_extn_compr_cap_init(in);
9582 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309583 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309584 if (ret)
9585 goto err_open;
9586 } else {
9587 in->config = pcm_config_audio_capture;
9588 in->config.rate = config->sample_rate;
9589 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309590 in->format = config->format;
9591 frame_size = audio_stream_in_frame_size(&in->stream);
9592 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009593 config->format,
9594 channel_count,
9595 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009596 /* prevent division-by-zero */
9597 if (frame_size == 0) {
9598 ALOGE("%s: Error frame_size==0", __func__);
9599 ret = -EINVAL;
9600 goto err_open;
9601 }
9602
Revathi Uddarajud2634032017-12-07 14:42:34 +05309603 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009604 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009605
Revathi Uddarajud2634032017-12-07 14:42:34 +05309606 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9607 /* optionally use VOIP usecase depending on config(s) */
9608 ret = adev_update_voice_comm_input_stream(in, config);
9609 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009610
Revathi Uddarajud2634032017-12-07 14:42:34 +05309611 if (ret) {
9612 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9613 goto err_open;
9614 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009615 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309616
9617 /* assign concurrent capture usecase if record has to caried out from
9618 * actual hardware input source */
9619 if (audio_extn_is_concurrent_capture_enabled() &&
9620 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309621 /* Acquire lock to avoid two concurrent use cases initialized to
9622 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009623
Samyak Jainc37062f2019-04-25 18:41:06 +05309624 if (in->usecase == USECASE_AUDIO_RECORD) {
9625 pthread_mutex_lock(&adev->lock);
9626 if (!(adev->pcm_record_uc_state)) {
9627 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9628 adev->pcm_record_uc_state = 1;
9629 pthread_mutex_unlock(&adev->lock);
9630 } else {
9631 pthread_mutex_unlock(&adev->lock);
9632 /* Assign compress record use case for second record */
9633 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9634 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9635 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9636 if (audio_extn_cin_applicable_stream(in)) {
9637 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309638 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309639 if (ret)
9640 goto err_open;
9641 }
9642 }
9643 }
kunleiz28c73e72019-03-27 17:24:04 +08009644 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009645 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309646 if (audio_extn_ssr_get_stream() != in)
9647 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009648
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009649 in->sample_rate = in->config.rate;
9650
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309651 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9652 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009653 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009654 in->sample_rate, in->bit_width,
9655 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309656 register_format(in->format, in->supported_formats);
9657 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9658 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309659
Aalique Grahame22e49102018-12-18 14:23:57 -08009660 in->error_log = error_log_create(
9661 ERROR_LOG_ENTRIES,
9662 1000000000 /* aggregate consecutive identical errors within one second */);
9663
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009664 /* This stream could be for sound trigger lab,
9665 get sound trigger pcm if present */
9666 audio_extn_sound_trigger_check_and_get_session(in);
9667
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309668 lock_input_stream(in);
9669 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9670 pthread_mutex_lock(&adev->lock);
9671 in->card_status = adev->card_status;
9672 pthread_mutex_unlock(&adev->lock);
9673 pthread_mutex_unlock(&in->lock);
9674
Aalique Grahame22e49102018-12-18 14:23:57 -08009675 stream_app_type_cfg_init(&in->app_type_cfg);
9676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009677 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009678
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009679 ret = io_streams_map_insert(adev, &in->stream.common,
9680 handle, AUDIO_PATCH_HANDLE_NONE);
9681 if (ret != 0)
9682 goto err_open;
9683
Derek Chenf939fb72018-11-13 13:34:41 -08009684 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9685 calloc(1, sizeof(streams_input_ctxt_t));
9686 if (in_ctxt == NULL) {
9687 ALOGE("%s fail to allocate input ctxt", __func__);
9688 ret = -ENOMEM;
9689 goto err_open;
9690 }
9691 in_ctxt->input = in;
9692
9693 pthread_mutex_lock(&adev->lock);
9694 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9695 pthread_mutex_unlock(&adev->lock);
9696
Eric Laurent994a6932013-07-17 11:51:42 -07009697 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009698 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009699
9700err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309701 if (in->usecase == USECASE_AUDIO_RECORD) {
9702 pthread_mutex_lock(&adev->lock);
9703 adev->pcm_record_uc_state = 0;
9704 pthread_mutex_unlock(&adev->lock);
9705 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009706 free(in);
9707 *stream_in = NULL;
9708 return ret;
9709}
9710
9711static void adev_close_input_stream(struct audio_hw_device *dev,
9712 struct audio_stream_in *stream)
9713{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009714 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009715 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009716 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309717
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309718 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009719
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009720 if (in == NULL) {
9721 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9722 return;
9723 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009724 io_streams_map_remove(adev, in->capture_handle);
9725
kunleiz70e57612018-12-28 17:50:23 +08009726 /* must deregister from sndmonitor first to prevent races
9727 * between the callback and close_stream
9728 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309729 audio_extn_snd_mon_unregister_listener(stream);
9730
kunleiz70e57612018-12-28 17:50:23 +08009731 /* Disable echo reference if there are no active input, hfp call
9732 * and sound trigger while closing input stream
9733 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009734 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009735 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009736 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9737 struct listnode out_devices;
9738 list_init(&out_devices);
9739 platform_set_echo_reference(adev, false, &out_devices);
9740 } else
kunleiz70e57612018-12-28 17:50:23 +08009741 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309742
Weiyin Jiang2995f662019-04-17 14:25:12 +08009743 error_log_destroy(in->error_log);
9744 in->error_log = NULL;
9745
Pallavid7c7a272018-01-16 11:22:55 +05309746
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009747 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309748 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009749 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309750 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009751 if (ret != 0)
9752 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9753 __func__, ret);
9754 } else
9755 in_standby(&stream->common);
9756
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009757 pthread_mutex_destroy(&in->lock);
9758 pthread_mutex_destroy(&in->pre_lock);
9759
Revathi Uddarajud2634032017-12-07 14:42:34 +05309760 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309761 if (in->usecase == USECASE_AUDIO_RECORD) {
9762 adev->pcm_record_uc_state = 0;
9763 }
9764
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009765 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9766 adev->enable_voicerx = false;
9767 }
9768
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009769 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009770 audio_extn_ssr_deinit();
9771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009772
Garmond Leunge2433c32017-09-28 21:51:22 -07009773 if (audio_extn_ffv_get_stream() == in) {
9774 audio_extn_ffv_stream_deinit();
9775 }
9776
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309777 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009778 audio_extn_compr_cap_format_supported(in->config.format))
9779 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309780
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309781 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309782 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009783
Mingming Yinfd7607b2016-01-22 12:48:44 -08009784 if (in->is_st_session) {
9785 ALOGV("%s: sound trigger pcm stop lab", __func__);
9786 audio_extn_sound_trigger_stop_lab(in);
9787 }
Derek Chenf939fb72018-11-13 13:34:41 -08009788 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9789 if (in_ctxt != NULL) {
9790 list_remove(&in_ctxt->list);
9791 free(in_ctxt);
9792 } else {
9793 ALOGW("%s, input stream already closed", __func__);
9794 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009795 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309796 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009797 return;
9798}
9799
Aalique Grahame22e49102018-12-18 14:23:57 -08009800/* verifies input and output devices and their capabilities.
9801 *
9802 * This verification is required when enabling extended bit-depth or
9803 * sampling rates, as not all qcom products support it.
9804 *
9805 * Suitable for calling only on initialization such as adev_open().
9806 * It fills the audio_device use_case_table[] array.
9807 *
9808 * Has a side-effect that it needs to configure audio routing / devices
9809 * in order to power up the devices and read the device parameters.
9810 * It does not acquire any hw device lock. Should restore the devices
9811 * back to "normal state" upon completion.
9812 */
9813static int adev_verify_devices(struct audio_device *adev)
9814{
9815 /* enumeration is a bit difficult because one really wants to pull
9816 * the use_case, device id, etc from the hidden pcm_device_table[].
9817 * In this case there are the following use cases and device ids.
9818 *
9819 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9820 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9821 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9822 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9823 * [USECASE_AUDIO_RECORD] = {0, 0},
9824 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9825 * [USECASE_VOICE_CALL] = {2, 2},
9826 *
9827 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9828 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9829 */
9830
9831 /* should be the usecases enabled in adev_open_input_stream() */
9832 static const int test_in_usecases[] = {
9833 USECASE_AUDIO_RECORD,
9834 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9835 };
9836 /* should be the usecases enabled in adev_open_output_stream()*/
9837 static const int test_out_usecases[] = {
9838 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9839 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9840 };
9841 static const usecase_type_t usecase_type_by_dir[] = {
9842 PCM_PLAYBACK,
9843 PCM_CAPTURE,
9844 };
9845 static const unsigned flags_by_dir[] = {
9846 PCM_OUT,
9847 PCM_IN,
9848 };
9849
9850 size_t i;
9851 unsigned dir;
9852 const unsigned card_id = adev->snd_card;
9853
9854 for (dir = 0; dir < 2; ++dir) {
9855 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9856 const unsigned flags_dir = flags_by_dir[dir];
9857 const size_t testsize =
9858 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9859 const int *testcases =
9860 dir ? test_in_usecases : test_out_usecases;
9861 const audio_devices_t audio_device =
9862 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9863
9864 for (i = 0; i < testsize; ++i) {
9865 const audio_usecase_t audio_usecase = testcases[i];
9866 int device_id;
9867 struct pcm_params **pparams;
9868 struct stream_out out;
9869 struct stream_in in;
9870 struct audio_usecase uc_info;
9871 int retval;
9872
9873 pparams = &adev->use_case_table[audio_usecase];
9874 pcm_params_free(*pparams); /* can accept null input */
9875 *pparams = NULL;
9876
9877 /* find the device ID for the use case (signed, for error) */
9878 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9879 if (device_id < 0)
9880 continue;
9881
9882 /* prepare structures for device probing */
9883 memset(&uc_info, 0, sizeof(uc_info));
9884 uc_info.id = audio_usecase;
9885 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009886 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009887 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009888 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009889 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009890 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009891 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9892 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009893 }
9894 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009895 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009896 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009897 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009898 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009899 uc_info.in_snd_device = SND_DEVICE_NONE;
9900 uc_info.out_snd_device = SND_DEVICE_NONE;
9901 list_add_tail(&adev->usecase_list, &uc_info.list);
9902
9903 /* select device - similar to start_(in/out)put_stream() */
9904 retval = select_devices(adev, audio_usecase);
9905 if (retval >= 0) {
9906 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9907#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009908 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009909 if (*pparams) {
9910 ALOGV("%s: (%s) card %d device %d", __func__,
9911 dir ? "input" : "output", card_id, device_id);
9912 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9913 } else {
9914 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9915 }
9916#endif
9917 }
9918
9919 /* deselect device - similar to stop_(in/out)put_stream() */
9920 /* 1. Get and set stream specific mixer controls */
9921 retval = disable_audio_route(adev, &uc_info);
9922 /* 2. Disable the rx device */
9923 retval = disable_snd_device(adev,
9924 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9925 list_remove(&uc_info.list);
9926 }
9927 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009928 return 0;
9929}
9930
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009931int update_patch(unsigned int num_sources,
9932 const struct audio_port_config *sources,
9933 unsigned int num_sinks,
9934 const struct audio_port_config *sinks,
9935 audio_patch_handle_t handle,
9936 struct audio_patch_info *p_info,
9937 patch_type_t patch_type, bool new_patch)
9938{
9939 ALOGD("%s: enter", __func__);
9940
9941 if (p_info == NULL) {
9942 ALOGE("%s: Invalid patch pointer", __func__);
9943 return -EINVAL;
9944 }
9945
9946 if (new_patch) {
9947 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9948 if (p_info->patch == NULL) {
9949 ALOGE("%s: Could not allocate patch", __func__);
9950 return -ENOMEM;
9951 }
9952 }
9953
9954 p_info->patch->id = handle;
9955 p_info->patch->num_sources = num_sources;
9956 p_info->patch->num_sinks = num_sinks;
9957
9958 for (int i = 0; i < num_sources; i++)
9959 p_info->patch->sources[i] = sources[i];
9960 for (int i = 0; i < num_sinks; i++)
9961 p_info->patch->sinks[i] = sinks[i];
9962
9963 p_info->patch_type = patch_type;
9964 return 0;
9965}
9966
9967audio_patch_handle_t generate_patch_handle()
9968{
9969 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9970 if (++patch_handle < 0)
9971 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9972 return patch_handle;
9973}
9974
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309975int adev_create_audio_patch(struct audio_hw_device *dev,
9976 unsigned int num_sources,
9977 const struct audio_port_config *sources,
9978 unsigned int num_sinks,
9979 const struct audio_port_config *sinks,
9980 audio_patch_handle_t *handle)
9981{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009982 int ret = 0;
9983 struct audio_device *adev = (struct audio_device *)dev;
9984 struct audio_patch_info *p_info = NULL;
9985 patch_type_t patch_type = PATCH_NONE;
9986 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9987 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9988 struct audio_stream_info *s_info = NULL;
9989 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009990 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009991 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9992 bool new_patch = false;
9993 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309994
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009995 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9996 num_sources, num_sinks, *handle);
9997
9998 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9999 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10000 ALOGE("%s: Invalid patch arguments", __func__);
10001 ret = -EINVAL;
10002 goto done;
10003 }
10004
10005 if (num_sources > 1) {
10006 ALOGE("%s: Multiple sources are not supported", __func__);
10007 ret = -EINVAL;
10008 goto done;
10009 }
10010
10011 if (sources == NULL || sinks == NULL) {
10012 ALOGE("%s: Invalid sources or sinks port config", __func__);
10013 ret = -EINVAL;
10014 goto done;
10015 }
10016
10017 ALOGV("%s: source role %d, source type %d", __func__,
10018 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010019 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010020
10021 // Populate source/sink information and fetch stream info
10022 switch (sources[0].type) {
10023 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10024 device_type = sources[0].ext.device.type;
10025 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010026 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010027 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10028 patch_type = PATCH_CAPTURE;
10029 io_handle = sinks[0].ext.mix.handle;
10030 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010031 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032 __func__, device_type, io_handle);
10033 } else {
10034 // Device to device patch is not implemented.
10035 // This space will need changes if audio HAL
10036 // handles device to device patches in the future.
10037 patch_type = PATCH_DEVICE_LOOPBACK;
10038 }
10039 break;
10040 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10041 io_handle = sources[0].ext.mix.handle;
10042 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010043 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010044 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010045 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010046 }
10047 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010048 ALOGD("%s: Playback patch from mix handle %d to device %x",
10049 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010050 break;
10051 case AUDIO_PORT_TYPE_SESSION:
10052 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010053 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10054 ret = -EINVAL;
10055 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010056 }
10057
10058 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060 // Generate patch info and update patch
10061 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010062 *handle = generate_patch_handle();
10063 p_info = (struct audio_patch_info *)
10064 calloc(1, sizeof(struct audio_patch_info));
10065 if (p_info == NULL) {
10066 ALOGE("%s: Failed to allocate memory", __func__);
10067 pthread_mutex_unlock(&adev->lock);
10068 ret = -ENOMEM;
10069 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010070 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010071 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010073 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010074 if (p_info == NULL) {
10075 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10076 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010077 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010078 ret = -EINVAL;
10079 goto done;
10080 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010081 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010082 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010083 *handle, p_info, patch_type, new_patch);
10084
10085 // Fetch stream info of associated mix for playback or capture patches
10086 if (p_info->patch_type == PATCH_PLAYBACK ||
10087 p_info->patch_type == PATCH_CAPTURE) {
10088 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10089 if (s_info == NULL) {
10090 ALOGE("%s: Failed to obtain stream info", __func__);
10091 if (new_patch)
10092 free(p_info);
10093 pthread_mutex_unlock(&adev->lock);
10094 ret = -EINVAL;
10095 goto done;
10096 }
10097 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10098 s_info->patch_handle = *handle;
10099 stream = s_info->stream;
10100 }
10101 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010102
10103 // Update routing for stream
10104 if (stream != NULL) {
10105 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010106 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010108 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010109 if (ret < 0) {
10110 pthread_mutex_lock(&adev->lock);
10111 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10112 if (new_patch)
10113 free(p_info);
10114 pthread_mutex_unlock(&adev->lock);
10115 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10116 goto done;
10117 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010118 }
10119
10120 // Add new patch to patch map
10121 if (!ret && new_patch) {
10122 pthread_mutex_lock(&adev->lock);
10123 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010124 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010125 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010126 }
10127
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128done:
10129 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010130 num_sources,
10131 sources,
10132 num_sinks,
10133 sinks,
10134 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010135 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010136 num_sources,
10137 sources,
10138 num_sinks,
10139 sinks,
10140 handle);
10141 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010142}
10143
10144int adev_release_audio_patch(struct audio_hw_device *dev,
10145 audio_patch_handle_t handle)
10146{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 struct audio_device *adev = (struct audio_device *) dev;
10148 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010149 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010150 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010151
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10153 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10154 ret = -EINVAL;
10155 goto done;
10156 }
10157
10158 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010159 pthread_mutex_lock(&adev->lock);
10160 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010161 if (p_info == NULL) {
10162 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010163 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010164 ret = -EINVAL;
10165 goto done;
10166 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010167 struct audio_patch *patch = p_info->patch;
10168 if (patch == NULL) {
10169 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010170 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010171 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010172 goto done;
10173 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010174 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10175 switch (patch->sources[0].type) {
10176 case AUDIO_PORT_TYPE_MIX:
10177 io_handle = patch->sources[0].ext.mix.handle;
10178 break;
10179 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010180 if (p_info->patch_type == PATCH_CAPTURE)
10181 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010182 break;
10183 case AUDIO_PORT_TYPE_SESSION:
10184 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010185 pthread_mutex_unlock(&adev->lock);
10186 ret = -EINVAL;
10187 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010188 }
10189
10190 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010191 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010192 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010193 if (patch_type == PATCH_PLAYBACK ||
10194 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010195 struct audio_stream_info *s_info =
10196 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10197 if (s_info == NULL) {
10198 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10199 pthread_mutex_unlock(&adev->lock);
10200 goto done;
10201 }
10202 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10203 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010204 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010205 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010206
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010207 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010208 struct listnode devices;
10209 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010210 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010211 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010212 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010213 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010214 }
10215
10216 if (ret < 0)
10217 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10218
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219done:
10220 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10221 audio_extn_auto_hal_release_audio_patch(dev, handle);
10222
10223 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010224 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010225}
10226
10227int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10228{
Derek Chenf13dd492018-11-13 14:53:51 -080010229 int ret = 0;
10230
10231 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10232 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10233 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010234}
10235
10236int adev_set_audio_port_config(struct audio_hw_device *dev,
10237 const struct audio_port_config *config)
10238{
Derek Chenf13dd492018-11-13 14:53:51 -080010239 int ret = 0;
10240
10241 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10242 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10243 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010244}
10245
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010246static int adev_dump(const audio_hw_device_t *device __unused,
10247 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010248{
10249 return 0;
10250}
10251
10252static int adev_close(hw_device_t *device)
10253{
Aalique Grahame22e49102018-12-18 14:23:57 -080010254 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010255 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010256
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010257 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010258 return 0;
10259
10260 pthread_mutex_lock(&adev_init_lock);
10261
10262 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010263 if (audio_extn_spkr_prot_is_enabled())
10264 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010265 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010266 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010267 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010268 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010269 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010270 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010271 audio_extn_utils_release_streams_cfg_lists(
10272 &adev->streams_output_cfg_list,
10273 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010274 if (audio_extn_qap_is_enabled())
10275 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010276 if (audio_extn_qaf_is_enabled())
10277 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010278 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010279 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010280 free(adev->snd_dev_ref_cnt);
10281 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010282 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10283 pcm_params_free(adev->use_case_table[i]);
10284 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010285 if (adev->adm_deinit)
10286 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010287 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010288 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010289 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010290 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010291 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010292 if (adev->device_cfg_params) {
10293 free(adev->device_cfg_params);
10294 adev->device_cfg_params = NULL;
10295 }
Derek Chend2530072014-11-24 12:39:14 -080010296 if(adev->ext_hw_plugin)
10297 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010298 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010299 free_map(adev->patch_map);
10300 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010301 free(device);
10302 adev = NULL;
10303 }
10304 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010305 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010306 return 0;
10307}
10308
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010309/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10310 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10311 * just that it _might_ work.
10312 */
10313static int period_size_is_plausible_for_low_latency(int period_size)
10314{
10315 switch (period_size) {
10316 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010317 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010318 case 240:
10319 case 320:
10320 case 480:
10321 return 1;
10322 default:
10323 return 0;
10324 }
10325}
10326
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010327static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10328{
10329 bool is_snd_card_status = false;
10330 bool is_ext_device_status = false;
10331 char value[32];
10332 int card = -1;
10333 card_status_t status;
10334
10335 if (cookie != adev || !parms)
10336 return;
10337
10338 if (!parse_snd_card_status(parms, &card, &status)) {
10339 is_snd_card_status = true;
10340 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10341 is_ext_device_status = true;
10342 } else {
10343 // not a valid event
10344 return;
10345 }
10346
10347 pthread_mutex_lock(&adev->lock);
10348 if (card == adev->snd_card || is_ext_device_status) {
10349 if (is_snd_card_status && adev->card_status != status) {
10350 adev->card_status = status;
10351 platform_snd_card_update(adev->platform, status);
10352 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010353 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010354 if (status == CARD_STATUS_OFFLINE)
10355 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010356 } else if (is_ext_device_status) {
10357 platform_set_parameters(adev->platform, parms);
10358 }
10359 }
10360 pthread_mutex_unlock(&adev->lock);
10361 return;
10362}
10363
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010364/* adev lock held */
10365int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010366{
10367 struct audio_usecase *uc_info;
10368 float left_p;
10369 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010370 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010371
10372 uc_info = get_usecase_from_list(adev, out->usecase);
10373 if (uc_info == NULL) {
10374 ALOGE("%s: Could not find the usecase (%d) in the list",
10375 __func__, out->usecase);
10376 return -EINVAL;
10377 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010378 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010379
10380 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10381 out->usecase, use_case_table[out->usecase]);
10382
10383 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010384 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010385 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010386 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010387 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010388 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10389 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010391 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10392 if (out->a2dp_compress_mute) {
10393 out->a2dp_compress_mute = false;
10394 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10395 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010396 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010397 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010398 out->muted = false;
10399 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010400 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010401 pthread_mutex_lock(&out->latch_lock);
Zhou Songc576a452019-09-09 14:17:40 +080010402 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10403 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010404 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010405 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010406 assign_devices(&devices, &out->device_list);
10407 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010408 left_p = out->volume_l;
10409 right_p = out->volume_r;
10410 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10411 compress_pause(out->compr);
10412 out_set_compr_volume(&out->stream, (float)0, (float)0);
10413 out->a2dp_compress_mute = true;
10414 select_devices(adev, out->usecase);
10415 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10416 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010417 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010418 out->volume_l = left_p;
10419 out->volume_r = right_p;
10420 }
Zhou Songc576a452019-09-09 14:17:40 +080010421 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010422 // mute for non offloaded streams
10423 if (audio_extn_a2dp_source_is_suspended()) {
10424 out->muted = true;
10425 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010426 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010427 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010428 }
10429 ALOGV("%s: exit", __func__);
10430 return 0;
10431}
10432
Haynes Mathew George01156f92018-04-13 15:29:54 -070010433void adev_on_battery_status_changed(bool charging)
10434{
10435 pthread_mutex_lock(&adev->lock);
10436 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10437 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010438 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010439 pthread_mutex_unlock(&adev->lock);
10440}
10441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010442static int adev_open(const hw_module_t *module, const char *name,
10443 hw_device_t **device)
10444{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010445 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010446 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010447 char mixer_ctl_name[128] = {0};
10448 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010449
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010450 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010451 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10452
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010453 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010454 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010455 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010456 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010457 ALOGD("%s: returning existing instance of adev", __func__);
10458 ALOGD("%s: exit", __func__);
10459 pthread_mutex_unlock(&adev_init_lock);
10460 return 0;
10461 }
10462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010463 adev = calloc(1, sizeof(struct audio_device));
10464
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010465 if (!adev) {
10466 pthread_mutex_unlock(&adev_init_lock);
10467 return -ENOMEM;
10468 }
10469
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010470 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10471
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010472 // register audio ext hidl at the earliest
10473 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010474#ifdef DYNAMIC_LOG_ENABLED
10475 register_for_dynamic_logging("hal");
10476#endif
10477
Derek Chenf939fb72018-11-13 13:34:41 -080010478 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010479 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010480 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10481 maj_version = atoi(value);
10482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010483 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010484 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010485 adev->device.common.module = (struct hw_module_t *)module;
10486 adev->device.common.close = adev_close;
10487
10488 adev->device.init_check = adev_init_check;
10489 adev->device.set_voice_volume = adev_set_voice_volume;
10490 adev->device.set_master_volume = adev_set_master_volume;
10491 adev->device.get_master_volume = adev_get_master_volume;
10492 adev->device.set_master_mute = adev_set_master_mute;
10493 adev->device.get_master_mute = adev_get_master_mute;
10494 adev->device.set_mode = adev_set_mode;
10495 adev->device.set_mic_mute = adev_set_mic_mute;
10496 adev->device.get_mic_mute = adev_get_mic_mute;
10497 adev->device.set_parameters = adev_set_parameters;
10498 adev->device.get_parameters = adev_get_parameters;
10499 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10500 adev->device.open_output_stream = adev_open_output_stream;
10501 adev->device.close_output_stream = adev_close_output_stream;
10502 adev->device.open_input_stream = adev_open_input_stream;
10503 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010504 adev->device.create_audio_patch = adev_create_audio_patch;
10505 adev->device.release_audio_patch = adev_release_audio_patch;
10506 adev->device.get_audio_port = adev_get_audio_port;
10507 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010508 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010509 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010510
10511 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010512 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010513 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010514 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010515 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010516 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010517 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010518 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010519 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010520 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010521 /* Init audio and voice feature */
10522 audio_extn_feature_init();
10523 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010524 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010525 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010526 list_init(&adev->active_inputs_list);
10527 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010528 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010529 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10530 audio_extn_utils_hash_eq);
10531 if (!adev->io_streams_map) {
10532 ALOGE("%s: Could not create io streams map", __func__);
10533 ret = -ENOMEM;
10534 goto adev_open_err;
10535 }
10536 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10537 audio_extn_utils_hash_eq);
10538 if (!adev->patch_map) {
10539 ALOGE("%s: Could not create audio patch map", __func__);
10540 ret = -ENOMEM;
10541 goto adev_open_err;
10542 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010543 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010544 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010545 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010546 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010547 adev->perf_lock_opts[0] = 0x101;
10548 adev->perf_lock_opts[1] = 0x20E;
10549 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010550 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010551 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010552 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010553 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010554 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010555
Zhou Song68ebc352019-12-05 17:11:15 +080010556 audio_extn_perf_lock_init();
10557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010558 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010559 adev->platform = platform_init(adev);
10560 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010561 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010562 ret = -EINVAL;
10563 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010564 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010565
Aalique Grahame22e49102018-12-18 14:23:57 -080010566 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010567 if (audio_extn_qap_is_enabled()) {
10568 ret = audio_extn_qap_init(adev);
10569 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010570 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010571 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010572 }
10573 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10574 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10575 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010576
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010577 if (audio_extn_qaf_is_enabled()) {
10578 ret = audio_extn_qaf_init(adev);
10579 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010580 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010581 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010582 }
10583
10584 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10585 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10586 }
10587
Derek Chenae7b0342019-02-08 15:17:04 -080010588 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010589 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10590
Eric Laurentc4aef752013-09-12 17:45:53 -070010591 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10592 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10593 if (adev->visualizer_lib == NULL) {
10594 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10595 } else {
10596 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10597 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010598 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010599 "visualizer_hal_start_output");
10600 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010601 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010602 "visualizer_hal_stop_output");
10603 }
10604 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010605 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010606 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010607 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010608 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010609 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010610 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010611
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010612 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10613 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10614 if (adev->offload_effects_lib == NULL) {
10615 ALOGE("%s: DLOPEN failed for %s", __func__,
10616 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10617 } else {
10618 ALOGV("%s: DLOPEN successful for %s", __func__,
10619 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10620 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010621 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010622 "offload_effects_bundle_hal_start_output");
10623 adev->offload_effects_stop_output =
10624 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10625 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010626 adev->offload_effects_set_hpx_state =
10627 (int (*)(bool))dlsym(adev->offload_effects_lib,
10628 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010629 adev->offload_effects_get_parameters =
10630 (void (*)(struct str_parms *, struct str_parms *))
10631 dlsym(adev->offload_effects_lib,
10632 "offload_effects_bundle_get_parameters");
10633 adev->offload_effects_set_parameters =
10634 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10635 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010636 }
10637 }
10638
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010639 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10640 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10641 if (adev->adm_lib == NULL) {
10642 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10643 } else {
10644 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10645 adev->adm_init = (adm_init_t)
10646 dlsym(adev->adm_lib, "adm_init");
10647 adev->adm_deinit = (adm_deinit_t)
10648 dlsym(adev->adm_lib, "adm_deinit");
10649 adev->adm_register_input_stream = (adm_register_input_stream_t)
10650 dlsym(adev->adm_lib, "adm_register_input_stream");
10651 adev->adm_register_output_stream = (adm_register_output_stream_t)
10652 dlsym(adev->adm_lib, "adm_register_output_stream");
10653 adev->adm_deregister_stream = (adm_deregister_stream_t)
10654 dlsym(adev->adm_lib, "adm_deregister_stream");
10655 adev->adm_request_focus = (adm_request_focus_t)
10656 dlsym(adev->adm_lib, "adm_request_focus");
10657 adev->adm_abandon_focus = (adm_abandon_focus_t)
10658 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010659 adev->adm_set_config = (adm_set_config_t)
10660 dlsym(adev->adm_lib, "adm_set_config");
10661 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10662 dlsym(adev->adm_lib, "adm_request_focus_v2");
10663 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10664 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10665 adev->adm_on_routing_change = (adm_on_routing_change_t)
10666 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010667 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10668 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010669 }
10670 }
10671
Aalique Grahame22e49102018-12-18 14:23:57 -080010672 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010673 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010674 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010675 //initialize this to false for now,
10676 //this will be set to true through set param
10677 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010678
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010679 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010680 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010681
10682 if (k_enable_extended_precision)
10683 adev_verify_devices(adev);
10684
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010685 adev->dsp_bit_width_enforce_mode =
10686 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010687
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010688 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10689 &adev->streams_output_cfg_list,
10690 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010691
Kiran Kandi910e1862013-10-29 13:29:42 -070010692 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010693
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010694 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010695 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010696 trial = atoi(value);
10697 if (period_size_is_plausible_for_low_latency(trial)) {
10698 pcm_config_low_latency.period_size = trial;
10699 pcm_config_low_latency.start_threshold = trial / 4;
10700 pcm_config_low_latency.avail_min = trial / 4;
10701 configured_low_latency_capture_period_size = trial;
10702 }
10703 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010704 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10705 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010706 trial = atoi(value);
10707 if (period_size_is_plausible_for_low_latency(trial)) {
10708 configured_low_latency_capture_period_size = trial;
10709 }
10710 }
10711
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010712 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10713
Eric Laurent4b084132018-10-19 17:33:43 -070010714 adev->camera_orientation = CAMERA_DEFAULT;
10715
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010716 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010717 af_period_multiplier = atoi(value);
10718 if (af_period_multiplier < 0)
10719 af_period_multiplier = 2;
10720 else if (af_period_multiplier > 4)
10721 af_period_multiplier = 4;
10722
10723 ALOGV("new period_multiplier = %d", af_period_multiplier);
10724 }
10725
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010726 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010727
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010728 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010729 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010730 pthread_mutex_unlock(&adev_init_lock);
10731
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010732 if (adev->adm_init)
10733 adev->adm_data = adev->adm_init();
10734
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010735 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010736 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010737
10738 audio_extn_snd_mon_init();
10739 pthread_mutex_lock(&adev->lock);
10740 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10741 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010742 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10743 /*
10744 * if the battery state callback happens before charging can be queried,
10745 * it will be guarded with the adev->lock held in the cb function and so
10746 * the callback value will reflect the latest state
10747 */
10748 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010749 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010750 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010751 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010752 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010753 /* Allocate memory for Device config params */
10754 adev->device_cfg_params = (struct audio_device_config_param*)
10755 calloc(platform_get_max_codec_backend(),
10756 sizeof(struct audio_device_config_param));
10757 if (adev->device_cfg_params == NULL)
10758 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010759
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010760 /*
10761 * Check if new PSPD matrix mixer control is supported. If not
10762 * supported, then set flag so that old mixer ctrl is sent while
10763 * sending pspd coefficients on older kernel version. Query mixer
10764 * control for default pcm id and channel value one.
10765 */
10766 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10767 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10768
10769 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10770 if (!ctl) {
10771 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10772 __func__, mixer_ctl_name);
10773 adev->use_old_pspd_mix_ctrl = true;
10774 }
10775
Eric Laurent994a6932013-07-17 11:51:42 -070010776 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010777 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010778
10779adev_open_err:
10780 free_map(adev->patch_map);
10781 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010782 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010783 pthread_mutex_destroy(&adev->lock);
10784 free(adev);
10785 adev = NULL;
10786 *device = NULL;
10787 pthread_mutex_unlock(&adev_init_lock);
10788 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010789}
10790
10791static struct hw_module_methods_t hal_module_methods = {
10792 .open = adev_open,
10793};
10794
10795struct audio_module HAL_MODULE_INFO_SYM = {
10796 .common = {
10797 .tag = HARDWARE_MODULE_TAG,
10798 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10799 .hal_api_version = HARDWARE_HAL_API_VERSION,
10800 .id = AUDIO_HARDWARE_MODULE_ID,
10801 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010802 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010803 .methods = &hal_module_methods,
10804 },
10805};