blob: f4b39fbf206936ecfeda4cc41f788892535f9747 [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
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530900static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530901{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530902 ALOGV("%s", __func__);
903 audio_route_apply_and_update_path(adev->audio_route,
904 "asrc-mode");
905 adev->asrc_mode_enabled = true;
906}
907
908static void disable_asrc_mode(struct audio_device *adev)
909{
910 ALOGV("%s", __func__);
911 audio_route_reset_and_update_path(adev->audio_route,
912 "asrc-mode");
913 adev->asrc_mode_enabled = false;
914}
915
916/*
917 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
918 * 44.1 or Native DSD backends are enabled for any of current use case.
919 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
920 * - Disable current mix path use case(Headphone backend) and re-enable it with
921 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
922 * e.g. Naitve DSD or Headphone 44.1 -> + 48
923 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530924static void check_and_set_asrc_mode(struct audio_device *adev,
925 struct audio_usecase *uc_info,
926 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530927{
928 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530929 int i, num_new_devices = 0;
930 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
931 /*
932 *Split snd device for new combo use case
933 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
934 */
935 if (platform_split_snd_device(adev->platform,
936 snd_device,
937 &num_new_devices,
938 split_new_snd_devices) == 0) {
939 for (i = 0; i < num_new_devices; i++)
940 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
941 } else {
942 int new_backend_idx = platform_get_backend_index(snd_device);
943 if (((new_backend_idx == HEADPHONE_BACKEND) ||
944 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
945 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
946 !adev->asrc_mode_enabled) {
947 struct listnode *node = NULL;
948 struct audio_usecase *uc = NULL;
949 struct stream_out *curr_out = NULL;
950 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
951 int i, num_devices, ret = 0;
952 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530953
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530954 list_for_each(node, &adev->usecase_list) {
955 uc = node_to_item(node, struct audio_usecase, list);
956 curr_out = (struct stream_out*) uc->stream.out;
957 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
958 /*
959 *Split snd device for existing combo use case
960 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
961 */
962 ret = platform_split_snd_device(adev->platform,
963 uc->out_snd_device,
964 &num_devices,
965 split_snd_devices);
966 if (ret < 0 || num_devices == 0) {
967 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
968 split_snd_devices[0] = uc->out_snd_device;
969 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800970 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530971 for (i = 0; i < num_devices; i++) {
972 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
973 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
974 if((new_backend_idx == HEADPHONE_BACKEND) &&
975 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
976 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
977 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
978 __func__);
979 enable_asrc_mode(adev);
980 break;
981 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
982 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
983 (usecase_backend_idx == HEADPHONE_BACKEND)) {
984 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
985 __func__);
986 disable_audio_route(adev, uc);
987 disable_snd_device(adev, uc->out_snd_device);
988 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
989 if (new_backend_idx == DSD_NATIVE_BACKEND)
990 audio_route_apply_and_update_path(adev->audio_route,
991 "hph-true-highquality-mode");
992 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
993 (curr_out->bit_width >= 24))
994 audio_route_apply_and_update_path(adev->audio_route,
995 "hph-highquality-mode");
996 enable_asrc_mode(adev);
997 enable_snd_device(adev, uc->out_snd_device);
998 enable_audio_route(adev, uc);
999 break;
1000 }
1001 }
1002 // reset split devices count
1003 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001004 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301005 if (adev->asrc_mode_enabled)
1006 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301007 }
1008 }
1009 }
1010}
1011
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001012static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1013 struct audio_effect_config effect_config,
1014 unsigned int param_value)
1015{
1016 char mixer_ctl_name[] = "Audio Effect";
1017 struct mixer_ctl *ctl;
1018 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001019 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001020
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001021 if (in == NULL) {
1022 ALOGE("%s: active input stream is NULL", __func__);
1023 return -EINVAL;
1024 }
1025
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001026 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1027 if (!ctl) {
1028 ALOGE("%s: Could not get mixer ctl - %s",
1029 __func__, mixer_ctl_name);
1030 return -EINVAL;
1031 }
1032
1033 set_values[0] = 1; //0:Rx 1:Tx
1034 set_values[1] = in->app_type_cfg.app_type;
1035 set_values[2] = (long)effect_config.module_id;
1036 set_values[3] = (long)effect_config.instance_id;
1037 set_values[4] = (long)effect_config.param_id;
1038 set_values[5] = param_value;
1039
1040 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1041
1042 return 0;
1043
1044}
1045
1046static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1047 int effect_type, unsigned int *param_value)
1048{
1049 int ret = 0;
1050 struct audio_effect_config other_effect_config;
1051 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001052 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001053
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001054 if (in == NULL) {
1055 ALOGE("%s: active input stream is NULL", __func__);
1056 return -EINVAL;
1057 }
1058
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001059 usecase = get_usecase_from_list(adev, in->usecase);
1060 if (!usecase)
1061 return -EINVAL;
1062
1063 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1064 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1065 if (ret < 0) {
1066 ALOGE("%s Failed to get effect params %d", __func__, ret);
1067 return ret;
1068 }
1069
1070 if (module_id == other_effect_config.module_id) {
1071 //Same module id for AEC/NS. Values need to be combined
1072 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1073 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1074 *param_value |= other_effect_config.param_value;
1075 }
1076 }
1077
1078 return ret;
1079}
1080
1081static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301082{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001083 struct audio_effect_config effect_config;
1084 struct audio_usecase *usecase = NULL;
1085 int ret = 0;
1086 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001087 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001088
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001089 if(!voice_extn_is_dynamic_ecns_enabled())
1090 return ENOSYS;
1091
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001092 if (!in) {
1093 ALOGE("%s: Invalid input stream", __func__);
1094 return -EINVAL;
1095 }
1096
1097 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1098
1099 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001100 if (usecase == NULL) {
1101 ALOGE("%s: Could not find the usecase (%d) in the list",
1102 __func__, in->usecase);
1103 return -EINVAL;
1104 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001105
1106 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1107 if (ret < 0) {
1108 ALOGE("%s Failed to get module id %d", __func__, ret);
1109 return ret;
1110 }
1111 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1112 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1113
1114 if(enable)
1115 param_value = effect_config.param_value;
1116
1117 /*Special handling for AEC & NS effects Param values need to be
1118 updated if module ids are same*/
1119
1120 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1121 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1122 if (ret < 0)
1123 return ret;
1124 }
1125
1126 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1127
1128 return ret;
1129}
1130
1131static void check_and_enable_effect(struct audio_device *adev)
1132{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001133 if(!voice_extn_is_dynamic_ecns_enabled())
1134 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001135
Eric Laurent637e2d42018-11-15 12:24:31 -08001136 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001137
Eric Laurent637e2d42018-11-15 12:24:31 -08001138 if (in != NULL && !in->standby) {
1139 if (in->enable_aec)
1140 enable_disable_effect(adev, EFFECT_AEC, true);
1141
1142 if (in->enable_ns &&
1143 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1144 enable_disable_effect(adev, EFFECT_NS, true);
1145 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001146 }
1147}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001148
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001149int pcm_ioctl(struct pcm *pcm, int request, ...)
1150{
1151 va_list ap;
1152 void * arg;
1153 int pcm_fd = *(int*)pcm;
1154
1155 va_start(ap, request);
1156 arg = va_arg(ap, void *);
1157 va_end(ap);
1158
1159 return ioctl(pcm_fd, request, arg);
1160}
1161
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001162int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001163 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001166 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301167 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301168 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001169 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301170 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001171
1172 if (usecase == NULL)
1173 return -EINVAL;
1174
1175 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1176
Carter Hsu2e429db2019-05-14 18:50:52 +08001177 if (usecase->type == PCM_CAPTURE) {
1178 struct stream_in *in = usecase->stream.in;
1179 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001181
1182 if (in) {
1183 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001184 list_init(&out_devices);
1185 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001186 struct listnode *node;
1187 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1188 USECASE_AUDIO_PLAYBACK_VOIP);
1189 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001190 assign_devices(&out_devices,
1191 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001192 } else if (adev->primary_output &&
1193 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001194 assign_devices(&out_devices,
1195 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 } else {
1197 list_for_each(node, &adev->usecase_list) {
1198 uinfo = node_to_item(node, struct audio_usecase, list);
1199 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001200 assign_devices(&out_devices,
1201 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001202 break;
1203 }
1204 }
1205 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206
1207 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 in->ec_opened = true;
1209 }
1210 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001211 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1212 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1213 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001214 snd_device = usecase->in_snd_device;
1215 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001218
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001219#ifdef DS1_DOLBY_DAP_ENABLED
1220 audio_extn_dolby_set_dmid(adev);
1221 audio_extn_dolby_set_endpoint(adev);
1222#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001223 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001224 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301225 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001226 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001227 if (audio_extn_is_maxx_audio_enabled())
1228 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301229 audio_extn_utils_send_audio_calibration(adev, usecase);
Weiyin Jiangaf20db92020-11-09 14:08:59 +08001230 if ((usecase->type == PCM_PLAYBACK) &&
1231 ((out = usecase->stream.out) != NULL)) {
1232 if (!is_offload_usecase(out->usecase)) {
1233 pthread_mutex_lock(&out->latch_lock);
1234 out->muted = false;
1235 pthread_mutex_unlock(&out->latch_lock);
1236 } else if (out->compr) {
Manish Dewangan58229382017-02-02 15:48:41 +05301237 audio_extn_utils_compress_set_clk_rec_mode(usecase);
Weiyin Jiangaf20db92020-11-09 14:08:59 +08001238 }
Manish Dewangan58229382017-02-02 15:48:41 +05301239 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301240
1241 if (usecase->type == PCM_CAPTURE) {
1242 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001243 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301244 ALOGD("%s: set custom mtmx params v1", __func__);
1245 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1246 }
1247 } else {
1248 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1249 }
Manish Dewangan58229382017-02-02 15:48:41 +05301250
Andy Hung756ecc12018-10-19 17:47:12 -07001251 // we shouldn't truncate mixer_path
1252 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1253 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1254 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001255 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001256 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301257 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1258 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1259 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1260 if (parms) {
1261 audio_extn_fm_set_parameters(adev, parms);
1262 str_parms_destroy(parms);
1263 }
1264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265 ALOGV("%s: exit", __func__);
1266 return 0;
1267}
1268
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001269int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001270 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001273 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301274 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001275
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301276 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001277 return -EINVAL;
1278
1279 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301280 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 snd_device = usecase->in_snd_device;
1282 else
1283 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001284
1285 /* disable island and power mode on supported device for voice call */
1286 if (usecase->type == VOICE_CALL) {
1287 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1288 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1289 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1290 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1291 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1292 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1293 ALOGD("%s: disable island cfg and power mode in voice tx path",
1294 __func__);
1295 }
1296 }
1297 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1298 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1299 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1300 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1301 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1302 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1303 ALOGD("%s: disable island cfg and power mode in voice rx path",
1304 __func__);
1305 }
1306 }
1307 }
1308
Andy Hung756ecc12018-10-19 17:47:12 -07001309 // we shouldn't truncate mixer_path
1310 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1311 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1312 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001313 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001314 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001315 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001316 if (usecase->type == PCM_CAPTURE) {
1317 struct stream_in *in = usecase->stream.in;
1318 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001319 struct listnode out_devices;
1320 list_init(&out_devices);
1321 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001322 in->ec_opened = false;
1323 }
1324 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001325 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301326 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327
1328 if (usecase->type == PCM_CAPTURE) {
1329 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001330 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301331 ALOGD("%s: reset custom mtmx params v1", __func__);
1332 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1333 }
1334 } else {
1335 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1336 }
1337
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001338 if ((usecase->type == PCM_PLAYBACK) &&
1339 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301340 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342 ALOGV("%s: exit", __func__);
1343 return 0;
1344}
1345
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001346int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001347 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301349 int i, num_devices = 0;
1350 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001351 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1352
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001353 if (snd_device < SND_DEVICE_MIN ||
1354 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001355 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001356 return -EINVAL;
1357 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001359 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001360 ALOGE("%s: Invalid sound device returned", __func__);
1361 return -EINVAL;
1362 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001363
1364 adev->snd_dev_ref_cnt[snd_device]++;
1365
1366 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1367 (platform_split_snd_device(adev->platform,
1368 snd_device,
1369 &num_devices,
1370 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001371 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001372 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001373 /* Set backend config for A2DP to ensure slimbus configuration
1374 is correct if A2DP is already active and backend is closed
1375 and re-opened */
1376 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1377 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 return 0;
1379 }
1380
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001381 if (audio_extn_spkr_prot_is_enabled())
1382 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001383
Aalique Grahame22e49102018-12-18 14:23:57 -08001384 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1385
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001386 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1387 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001388 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1389 goto err;
1390 }
1391 audio_extn_dev_arbi_acquire(snd_device);
1392 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001393 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001394 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001395 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001396 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001397 } else if (platform_split_snd_device(adev->platform,
1398 snd_device,
1399 &num_devices,
1400 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301401 for (i = 0; i < num_devices; i++) {
1402 enable_snd_device(adev, new_snd_devices[i]);
1403 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001404 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001405 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001406 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301407
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001408 /* enable island and power mode on supported device */
1409 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1410 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1411 platform_set_island_cfg_on_device(adev, snd_device, true);
1412 platform_set_power_mode_on_device(adev, snd_device, true);
1413 ALOGD("%s: enable island cfg and power mode on: %s",
1414 __func__, device_name);
1415 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301416
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301417 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1418 if (audio_extn_a2dp_start_playback() < 0) {
1419 ALOGE(" fail to configure A2dp Source control path ");
1420 goto err;
1421 } else {
1422 adev->a2dp_started = true;
1423 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001424 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001425
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001426 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1427 (audio_extn_a2dp_start_capture() < 0)) {
1428 ALOGE(" fail to configure A2dp Sink control path ");
1429 goto err;
1430 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301431
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001432 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1433 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1434 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1435 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1436 ALOGE(" fail to configure sco control path ");
1437 goto err;
1438 }
Zhou Song12c29502019-03-16 10:37:18 +08001439 }
1440
Zhou Song331c8e52019-08-26 14:16:12 +08001441 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001442 /* due to the possibility of calibration overwrite between listen
1443 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001444 audio_extn_sound_trigger_update_device_status(snd_device,
1445 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301446 audio_extn_listen_update_device_status(snd_device,
1447 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001448 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001449 audio_extn_sound_trigger_update_device_status(snd_device,
1450 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301451 audio_extn_listen_update_device_status(snd_device,
1452 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001453 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001454 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001455 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001456 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301457
1458 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1459 !adev->native_playback_enabled &&
1460 audio_is_true_native_stream_active(adev)) {
1461 ALOGD("%s: %d: napb: enabling native mode in hardware",
1462 __func__, __LINE__);
1463 audio_route_apply_and_update_path(adev->audio_route,
1464 "true-native-mode");
1465 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301466 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301467 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1468 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001469 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001470 ALOGD("%s: init ec ref loopback", __func__);
1471 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1472 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001475err:
1476 adev->snd_dev_ref_cnt[snd_device]--;
1477 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478}
1479
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001480int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001481 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301483 int i, num_devices = 0;
1484 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001485 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1486
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001487 if (snd_device < SND_DEVICE_MIN ||
1488 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001489 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001490 return -EINVAL;
1491 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001492
1493 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1494 ALOGE("%s: Invalid sound device returned", __func__);
1495 return -EINVAL;
1496 }
1497
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1499 ALOGE("%s: device ref cnt is already 0", __func__);
1500 return -EINVAL;
1501 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001502
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001504
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001505
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001507 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301508
Aalique Grahame22e49102018-12-18 14:23:57 -08001509 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1510
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001511 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1512 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001513 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001514
1515 // when speaker device is disabled, reset swap.
1516 // will be renabled on usecase start
1517 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001518 } else if (platform_split_snd_device(adev->platform,
1519 snd_device,
1520 &num_devices,
1521 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301522 for (i = 0; i < num_devices; i++) {
1523 disable_snd_device(adev, new_snd_devices[i]);
1524 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001525 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001526 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001527 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001528 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001529
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301530 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301531 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301532 adev->a2dp_started = false;
1533 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001534 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001535 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001536 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301537 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001538 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301539 adev->native_playback_enabled) {
1540 ALOGD("%s: %d: napb: disabling native mode in hardware",
1541 __func__, __LINE__);
1542 audio_route_reset_and_update_path(adev->audio_route,
1543 "true-native-mode");
1544 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001545 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301546 adev->asrc_mode_enabled) {
1547 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301548 disable_asrc_mode(adev);
1549 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001550 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301551 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001552 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001553 ALOGD("%s: deinit ec ref loopback", __func__);
1554 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1555 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001556
1557 audio_extn_utils_release_snd_device(snd_device);
1558 } else {
1559 if (platform_split_snd_device(adev->platform,
1560 snd_device,
1561 &num_devices,
1562 new_snd_devices) == 0) {
1563 for (i = 0; i < num_devices; i++) {
1564 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1565 }
1566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 return 0;
1570}
1571
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001572/*
1573 legend:
1574 uc - existing usecase
1575 new_uc - new usecase
1576 d1, d11, d2 - SND_DEVICE enums
1577 a1, a2 - corresponding ANDROID device enums
1578 B1, B2 - backend strings
1579
1580case 1
1581 uc->dev d1 (a1) B1
1582 new_uc->dev d1 (a1), d2 (a2) B1, B2
1583
1584 resolution: disable and enable uc->dev on d1
1585
1586case 2
1587 uc->dev d1 (a1) B1
1588 new_uc->dev d11 (a1) B1
1589
1590 resolution: need to switch uc since d1 and d11 are related
1591 (e.g. speaker and voice-speaker)
1592 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1593
1594case 3
1595 uc->dev d1 (a1) B1
1596 new_uc->dev d2 (a2) B2
1597
1598 resolution: no need to switch uc
1599
1600case 4
1601 uc->dev d1 (a1) B1
1602 new_uc->dev d2 (a2) B1
1603
1604 resolution: disable enable uc-dev on d2 since backends match
1605 we cannot enable two streams on two different devices if they
1606 share the same backend. e.g. if offload is on speaker device using
1607 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1608 using the same backend, offload must also be switched to voice-handset.
1609
1610case 5
1611 uc->dev d1 (a1) B1
1612 new_uc->dev d1 (a1), d2 (a2) B1
1613
1614 resolution: disable enable uc-dev on d2 since backends match
1615 we cannot enable two streams on two different devices if they
1616 share the same backend.
1617
1618case 6
1619 uc->dev d1 (a1) B1
1620 new_uc->dev d2 (a1) B2
1621
1622 resolution: no need to switch
1623
1624case 7
1625 uc->dev d1 (a1), d2 (a2) B1, B2
1626 new_uc->dev d1 (a1) B1
1627
1628 resolution: no need to switch
1629
Zhou Song4ba65882018-07-09 14:48:07 +08001630case 8
1631 uc->dev d1 (a1) B1
1632 new_uc->dev d11 (a1), d2 (a2) B1, B2
1633 resolution: compared to case 1, for this case, d1 and d11 are related
1634 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301635
1636case 9
1637 uc->dev d1 (a1), d2(a2) B1 B2
1638 new_uc->dev d1 (a1), d22 (a2) B1, B2
1639 resolution: disable enable uc-dev on d2 since backends match
1640 we cannot enable two streams on two different devices if they
1641 share the same backend. This is special case for combo use case
1642 with a2dp and sco devices which uses same backend.
1643 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001644*/
1645static snd_device_t derive_playback_snd_device(void * platform,
1646 struct audio_usecase *uc,
1647 struct audio_usecase *new_uc,
1648 snd_device_t new_snd_device)
1649{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001650 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001651
1652 snd_device_t d1 = uc->out_snd_device;
1653 snd_device_t d2 = new_snd_device;
1654
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001655 list_init(&a1);
1656 list_init(&a2);
1657
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301659 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001660 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1661 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301662 break;
1663 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001664 assign_devices(&a1, &uc->stream.out->device_list);
1665 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301666 break;
1667 }
1668
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001669 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001670 if (!compare_devices(&a1, &a2) &&
1671 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001672 snd_device_t d3[2];
1673 int num_devices = 0;
1674 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001675 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001676 &num_devices,
1677 d3);
1678 if (ret < 0) {
1679 if (ret != -ENOSYS) {
1680 ALOGW("%s failed to split snd_device %d",
1681 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001682 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001683 }
1684 goto end;
1685 }
1686
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001687 if (platform_check_backends_match(d3[0], d3[1])) {
1688 return d2; // case 5
1689 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301690 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1691 platform_check_backends_match(d1, d2))
1692 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001693 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301694 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001695 // check if d1 is related to any of d3's
1696 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001697 return d1; // case 1
1698 else
1699 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001700 }
1701 } else {
1702 if (platform_check_backends_match(d1, d2)) {
1703 return d2; // case 2, 4
1704 } else {
1705 return d1; // case 6, 3
1706 }
1707 }
1708
1709end:
1710 return d2; // return whatever was calculated before.
1711}
1712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301714 struct audio_usecase *uc_info,
1715 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001716{
1717 struct listnode *node;
1718 struct audio_usecase *usecase;
1719 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301720 snd_device_t uc_derive_snd_device;
1721 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001722 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1723 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001724 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301725 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001726 /*
1727 * This function is to make sure that all the usecases that are active on
1728 * the hardware codec backend are always routed to any one device that is
1729 * handled by the hardware codec.
1730 * For example, if low-latency and deep-buffer usecases are currently active
1731 * on speaker and out_set_parameters(headset) is received on low-latency
1732 * output, then we have to make sure deep-buffer is also switched to headset,
1733 * because of the limitation that both the devices cannot be enabled
1734 * at the same time as they share the same backend.
1735 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001736 /*
1737 * This call is to check if we need to force routing for a particular stream
1738 * If there is a backend configuration change for the device when a
1739 * new stream starts, then ADM needs to be closed and re-opened with the new
1740 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001741 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001742 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001743 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1744 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301745 /* For a2dp device reconfigure all active sessions
1746 * with new AFE encoder format based on a2dp state
1747 */
1748 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301749 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1750 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301751 audio_extn_a2dp_is_force_device_switch()) {
1752 force_routing = true;
1753 force_restart_session = true;
1754 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001755
1756 /*
1757 * Island cfg and power mode config needs to set before AFE port start.
1758 * Set force routing in case of voice device was enable before.
1759 */
1760 if (uc_info->type == VOICE_CALL &&
1761 voice_extn_is_voice_power_mode_supported() &&
1762 platform_check_and_update_island_power_status(adev->platform,
1763 uc_info,
1764 snd_device)) {
1765 force_routing = true;
1766 ALOGD("%s:becf: force routing %d for power mode supported device",
1767 __func__, force_routing);
1768 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301769 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1770
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001771 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001772 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001773 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001774 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1775 switch_device[i] = false;
1776
1777 list_for_each(node, &adev->usecase_list) {
1778 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001779
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301780 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1781 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301782 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301783 platform_get_snd_device_name(usecase->out_snd_device),
1784 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301785 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1786 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301787 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1788 usecase, uc_info, snd_device);
1789 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001790 (is_codec_backend_out_device_type(&usecase->device_list) ||
1791 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1792 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1793 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1794 is_a2dp_out_device_type(&usecase->device_list) ||
1795 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301796 ((force_restart_session) ||
1797 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301798 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1799 __func__, use_case_table[usecase->id],
1800 platform_get_snd_device_name(usecase->out_snd_device));
1801 disable_audio_route(adev, usecase);
1802 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301803 /* Enable existing usecase on derived playback device */
1804 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301805 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301806 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807 }
1808 }
1809
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301810 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1811 num_uc_to_switch);
1812
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001814 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301816 /* Make sure the previous devices to be disabled first and then enable the
1817 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001818 list_for_each(node, &adev->usecase_list) {
1819 usecase = node_to_item(node, struct audio_usecase, list);
1820 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001821 /* Check if output sound device to be switched can be split and if any
1822 of the split devices match with derived sound device */
1823 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1824 &num_devices, split_snd_devices) == 0) {
1825 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1826 for (i = 0; i < num_devices; i++) {
1827 /* Disable devices that do not match with derived sound device */
1828 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1829 disable_snd_device(adev, split_snd_devices[i]);
1830 }
1831 } else {
1832 disable_snd_device(adev, usecase->out_snd_device);
1833 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834 }
1835 }
1836
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001840 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1841 &num_devices, split_snd_devices) == 0) {
1842 /* Enable derived sound device only if it does not match with
1843 one of the split sound devices. This is because the matching
1844 sound device was not disabled */
1845 bool should_enable = true;
1846 for (i = 0; i < num_devices; i++) {
1847 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1848 should_enable = false;
1849 break;
1850 }
1851 }
1852 if (should_enable)
1853 enable_snd_device(adev, derive_snd_device[usecase->id]);
1854 } else {
1855 enable_snd_device(adev, derive_snd_device[usecase->id]);
1856 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001857 }
1858 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001859
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001860 /* Re-route all the usecases on the shared backend other than the
1861 specified usecase to new snd devices */
1862 list_for_each(node, &adev->usecase_list) {
1863 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301864 /* Update the out_snd_device only before enabling the audio route */
1865 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301866 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301867 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1868 use_case_table[usecase->id],
1869 platform_get_snd_device_name(usecase->out_snd_device));
1870 /* Update voc calibration before enabling Voice/VoIP route */
1871 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1872 status = platform_switch_voice_call_device_post(adev->platform,
1873 usecase->out_snd_device,
1874 platform_get_input_snd_device(
1875 adev->platform, NULL,
1876 &uc_info->device_list,
1877 usecase->type));
1878 enable_audio_route(adev, usecase);
1879 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1880 out_set_voip_volume(&usecase->stream.out->stream,
1881 usecase->stream.out->volume_l,
1882 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001884 }
1885 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 }
1887}
1888
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301889static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001890 struct audio_usecase *uc_info,
1891 snd_device_t snd_device)
1892{
1893 struct listnode *node;
1894 struct audio_usecase *usecase;
1895 bool switch_device[AUDIO_USECASE_MAX];
1896 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001897 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001898 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001899
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301900 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1901 snd_device);
1902 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301903
1904 /*
1905 * Make sure out devices is checked against out codec backend device and
1906 * also in devices against in codec backend. Checking out device against in
1907 * codec backend or vice versa causes issues.
1908 */
1909 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001910 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001911
1912 /*
1913 * Island cfg and power mode config needs to set before AFE port start.
1914 * Set force routing in case of voice device was enable before.
1915 */
1916
1917 if (uc_info->type == VOICE_CALL &&
1918 voice_extn_is_voice_power_mode_supported() &&
1919 platform_check_and_update_island_power_status(adev->platform,
1920 uc_info,
1921 snd_device)) {
1922 force_routing = true;
1923 ALOGD("%s:becf: force routing %d for power mode supported device",
1924 __func__, force_routing);
1925 }
1926
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001927 /*
1928 * This function is to make sure that all the active capture usecases
1929 * are always routed to the same input sound device.
1930 * For example, if audio-record and voice-call usecases are currently
1931 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1932 * is received for voice call then we have to make sure that audio-record
1933 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1934 * because of the limitation that two devices cannot be enabled
1935 * at the same time if they share the same backend.
1936 */
1937 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1938 switch_device[i] = false;
1939
1940 list_for_each(node, &adev->usecase_list) {
1941 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301942 /*
1943 * TODO: Enhance below condition to handle BT sco/USB multi recording
1944 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301945
1946 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1947 (usecase->in_snd_device != snd_device || force_routing));
1948 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1949 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1950 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001951 ((backend_check_cond &&
1952 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001953 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001954 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001955 is_single_device_type_equal(&usecase->device_list,
1956 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001957 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001958 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001959 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301960 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001961 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001962 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001963 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001964 switch_device[usecase->id] = true;
1965 num_uc_to_switch++;
1966 }
1967 }
1968
1969 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001970 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001971
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301972 /* Make sure the previous devices to be disabled first and then enable the
1973 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001974 list_for_each(node, &adev->usecase_list) {
1975 usecase = node_to_item(node, struct audio_usecase, list);
1976 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001977 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001978 }
1979 }
1980
1981 list_for_each(node, &adev->usecase_list) {
1982 usecase = node_to_item(node, struct audio_usecase, list);
1983 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001984 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001985 }
1986 }
1987
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001988 /* Re-route all the usecases on the shared backend other than the
1989 specified usecase to new snd devices */
1990 list_for_each(node, &adev->usecase_list) {
1991 usecase = node_to_item(node, struct audio_usecase, list);
1992 /* Update the in_snd_device only before enabling the audio route */
1993 if (switch_device[usecase->id] ) {
1994 usecase->in_snd_device = snd_device;
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301995 /* Update voc calibration before enabling Voice/VoIP route */
1996 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1997 snd_device_t voip_snd_device;
1998 voip_snd_device = platform_get_output_snd_device(adev->platform,
1999 usecase->stream.out,
2000 usecase->type);
2001 status = platform_switch_voice_call_device_post(adev->platform,
2002 voip_snd_device,
2003 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002004 }
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302005 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002006 }
2007 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002008 }
2009}
2010
Mingming Yin3a941d42016-02-17 18:08:05 -08002011static void reset_hdmi_sink_caps(struct stream_out *out) {
2012 int i = 0;
2013
2014 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2015 out->supported_channel_masks[i] = 0;
2016 }
2017 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2018 out->supported_formats[i] = 0;
2019 }
2020 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2021 out->supported_sample_rates[i] = 0;
2022 }
2023}
2024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002026static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027{
Mingming Yin3a941d42016-02-17 18:08:05 -08002028 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002029 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2030 out->extconn.cs.controller,
2031 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032
Mingming Yin3a941d42016-02-17 18:08:05 -08002033 reset_hdmi_sink_caps(out);
2034
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002035 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002036 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002037 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002038 out->extconn.cs.stream);
2039 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002040 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002041 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002042 }
2043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002046 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002047 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002048 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2049 case 6:
2050 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2051 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2052 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2053 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2054 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2055 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 break;
2057 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002058 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002059 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 break;
2061 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002062
2063 // check channel format caps
2064 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002065 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2066 out->extconn.cs.controller,
2067 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002068 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2069 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2070 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2071 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2072 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2073 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2074 }
2075
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002076 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2077 out->extconn.cs.controller,
2078 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002079 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2080 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2081 }
2082
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002083 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2084 out->extconn.cs.controller,
2085 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002086 ALOGV(":%s HDMI supports DTS format", __func__);
2087 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2088 }
2089
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002090 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2091 out->extconn.cs.controller,
2092 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002093 ALOGV(":%s HDMI supports DTS HD format", __func__);
2094 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2095 }
2096
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002097 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2098 out->extconn.cs.controller,
2099 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002100 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2101 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2102 }
2103
Mingming Yin3a941d42016-02-17 18:08:05 -08002104
2105 // check sample rate caps
2106 i = 0;
2107 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002108 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2109 out->extconn.cs.controller,
2110 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002111 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2112 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2113 }
2114 }
2115
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002116 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117}
2118
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002119static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2120 uint32_t *supported_sample_rates __unused,
2121 uint32_t max_rates __unused)
2122{
2123 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2124 supported_sample_rates,
2125 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302126 ssize_t i = 0;
2127
2128 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002129 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2130 supported_sample_rates[i]);
2131 }
2132 return count;
2133}
2134
2135static inline int read_usb_sup_channel_masks(bool is_playback,
2136 audio_channel_mask_t *supported_channel_masks,
2137 uint32_t max_masks)
2138{
2139 int channels = audio_extn_usb_get_max_channels(is_playback);
2140 int channel_count;
2141 uint32_t num_masks = 0;
2142 if (channels > MAX_HIFI_CHANNEL_COUNT)
2143 channels = MAX_HIFI_CHANNEL_COUNT;
2144
2145 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002146 // start from 2 channels as framework currently doesn't support mono.
2147 if (channels >= FCC_2) {
2148 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2149 }
2150 for (channel_count = FCC_2;
2151 channel_count <= channels && num_masks < max_masks;
2152 ++channel_count) {
2153 supported_channel_masks[num_masks++] =
2154 audio_channel_mask_for_index_assignment_from_count(channel_count);
2155 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002156 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002157 // For capture we report all supported channel masks from 1 channel up.
2158 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002159 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2160 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002161 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2162 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2163 if (channel_count <= FCC_2) {
2164 mask = audio_channel_in_mask_from_count(channel_count);
2165 supported_channel_masks[num_masks++] = mask;
2166 }
2167 const audio_channel_mask_t index_mask =
2168 audio_channel_mask_for_index_assignment_from_count(channel_count);
2169 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2170 supported_channel_masks[num_masks++] = index_mask;
2171 }
2172 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002173 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302174
vincenttewf51c94e2019-05-07 10:28:53 +08002175 for (size_t i = 0; i < num_masks; ++i) {
2176 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2177 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302178 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002179 return num_masks;
2180}
2181
2182static inline int read_usb_sup_formats(bool is_playback __unused,
2183 audio_format_t *supported_formats,
2184 uint32_t max_formats __unused)
2185{
2186 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2187 switch (bitwidth) {
2188 case 24:
2189 // XXX : usb.c returns 24 for s24 and s24_le?
2190 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2191 break;
2192 case 32:
2193 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2194 break;
2195 case 16:
2196 default :
2197 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2198 break;
2199 }
2200 ALOGV("%s: %s supported format %d", __func__,
2201 is_playback ? "P" : "C", bitwidth);
2202 return 1;
2203}
2204
2205static inline int read_usb_sup_params_and_compare(bool is_playback,
2206 audio_format_t *format,
2207 audio_format_t *supported_formats,
2208 uint32_t max_formats,
2209 audio_channel_mask_t *mask,
2210 audio_channel_mask_t *supported_channel_masks,
2211 uint32_t max_masks,
2212 uint32_t *rate,
2213 uint32_t *supported_sample_rates,
2214 uint32_t max_rates) {
2215 int ret = 0;
2216 int num_formats;
2217 int num_masks;
2218 int num_rates;
2219 int i;
2220
2221 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2222 max_formats);
2223 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2224 max_masks);
2225
2226 num_rates = read_usb_sup_sample_rates(is_playback,
2227 supported_sample_rates, max_rates);
2228
2229#define LUT(table, len, what, dflt) \
2230 for (i=0; i<len && (table[i] != what); i++); \
2231 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2232
2233 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2234 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2235 LUT(supported_sample_rates, num_rates, *rate, 0);
2236
2237#undef LUT
2238 return ret < 0 ? -EINVAL : 0; // HACK TBD
2239}
2240
Alexy Josephb1379942016-01-29 15:49:38 -08002241audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002242 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002243{
2244 struct audio_usecase *usecase;
2245 struct listnode *node;
2246
2247 list_for_each(node, &adev->usecase_list) {
2248 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002249 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002250 ALOGV("%s: usecase id %d", __func__, usecase->id);
2251 return usecase->id;
2252 }
2253 }
2254 return USECASE_INVALID;
2255}
2256
Alexy Josephb1379942016-01-29 15:49:38 -08002257struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002258 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259{
2260 struct audio_usecase *usecase;
2261 struct listnode *node;
2262
2263 list_for_each(node, &adev->usecase_list) {
2264 usecase = node_to_item(node, struct audio_usecase, list);
2265 if (usecase->id == uc_id)
2266 return usecase;
2267 }
2268 return NULL;
2269}
2270
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302271/*
2272 * is a true native playback active
2273 */
2274bool audio_is_true_native_stream_active(struct audio_device *adev)
2275{
2276 bool active = false;
2277 int i = 0;
2278 struct listnode *node;
2279
2280 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2281 ALOGV("%s:napb: not in true mode or non hdphones device",
2282 __func__);
2283 active = false;
2284 goto exit;
2285 }
2286
2287 list_for_each(node, &adev->usecase_list) {
2288 struct audio_usecase *uc;
2289 uc = node_to_item(node, struct audio_usecase, list);
2290 struct stream_out *curr_out =
2291 (struct stream_out*) uc->stream.out;
2292
2293 if (curr_out && PCM_PLAYBACK == uc->type) {
2294 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2295 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2296 uc->id, curr_out->sample_rate,
2297 curr_out->bit_width,
2298 platform_get_snd_device_name(uc->out_snd_device));
2299
2300 if (is_offload_usecase(uc->id) &&
2301 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2302 active = true;
2303 ALOGD("%s:napb:native stream detected", __func__);
2304 }
2305 }
2306 }
2307exit:
2308 return active;
2309}
2310
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002311uint32_t adev_get_dsp_bit_width_enforce_mode()
2312{
2313 if (adev == NULL) {
2314 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2315 return 0;
2316 }
2317 return adev->dsp_bit_width_enforce_mode;
2318}
2319
2320static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2321{
2322 char value[PROPERTY_VALUE_MAX];
2323 int trial;
2324 uint32_t dsp_bit_width_enforce_mode = 0;
2325
2326 if (!mixer) {
2327 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2328 __func__);
2329 return 0;
2330 }
2331
2332 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2333 value, NULL) > 0) {
2334 trial = atoi(value);
2335 switch (trial) {
2336 case 16:
2337 dsp_bit_width_enforce_mode = 16;
2338 break;
2339 case 24:
2340 dsp_bit_width_enforce_mode = 24;
2341 break;
2342 case 32:
2343 dsp_bit_width_enforce_mode = 32;
2344 break;
2345 default:
2346 dsp_bit_width_enforce_mode = 0;
2347 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2348 break;
2349 }
2350 }
2351
2352 return dsp_bit_width_enforce_mode;
2353}
2354
2355static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2356 uint32_t enforce_mode,
2357 bool enable)
2358{
2359 struct mixer_ctl *ctl = NULL;
2360 const char *mixer_ctl_name = "ASM Bit Width";
2361 uint32_t asm_bit_width_mode = 0;
2362
2363 if (enforce_mode == 0) {
2364 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2365 return;
2366 }
2367
2368 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2369 if (!ctl) {
2370 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2371 __func__, mixer_ctl_name);
2372 return;
2373 }
2374
2375 if (enable)
2376 asm_bit_width_mode = enforce_mode;
2377 else
2378 asm_bit_width_mode = 0;
2379
2380 ALOGV("%s DSP bit width feature status is %d width=%d",
2381 __func__, enable, asm_bit_width_mode);
2382 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2383 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2384 asm_bit_width_mode);
2385
2386 return;
2387}
2388
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302389/*
2390 * if native DSD playback active
2391 */
2392bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2393{
2394 bool active = false;
2395 struct listnode *node = NULL;
2396 struct audio_usecase *uc = NULL;
2397 struct stream_out *curr_out = NULL;
2398
2399 list_for_each(node, &adev->usecase_list) {
2400 uc = node_to_item(node, struct audio_usecase, list);
2401 curr_out = (struct stream_out*) uc->stream.out;
2402
2403 if (curr_out && PCM_PLAYBACK == uc->type &&
2404 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2405 active = true;
2406 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302407 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302408 }
2409 }
2410 return active;
2411}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302412
2413static bool force_device_switch(struct audio_usecase *usecase)
2414{
2415 bool ret = false;
2416 bool is_it_true_mode = false;
2417
Zhou Song30f2c3e2018-02-08 14:02:15 +08002418 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302419 usecase->type == TRANSCODE_LOOPBACK_RX ||
2420 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002421 return false;
2422 }
2423
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002424 if(usecase->stream.out == NULL) {
2425 ALOGE("%s: stream.out is NULL", __func__);
2426 return false;
2427 }
2428
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302429 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002430 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002431 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2432 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302433 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2434 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2435 (!is_it_true_mode && adev->native_playback_enabled)){
2436 ret = true;
2437 ALOGD("napb: time to toggle native mode");
2438 }
2439 }
2440
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302441 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302442 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2443 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002444 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302445 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302446 ALOGD("Force a2dp device switch to update new encoder config");
2447 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002448 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302449
Florian Pfister1a84f312018-07-19 14:38:18 +02002450 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302451 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2452 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002453 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302454 return ret;
2455}
2456
Aalique Grahame22e49102018-12-18 14:23:57 -08002457static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2458{
2459 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2460}
2461
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302462bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2463{
2464 bool ret=false;
2465 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002466 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2467 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302468 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2469 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002470 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302471 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002472 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2473 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302474 ret = true;
2475
2476 return ret;
2477}
2478
2479bool is_a2dp_device(snd_device_t out_snd_device)
2480{
2481 bool ret=false;
2482 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2483 ret = true;
2484
2485 return ret;
2486}
2487
2488bool is_bt_soc_on(struct audio_device *adev)
2489{
2490 struct mixer_ctl *ctl;
2491 char *mixer_ctl_name = "BT SOC status";
2492 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2493 bool bt_soc_status = true;
2494 if (!ctl) {
2495 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2496 __func__, mixer_ctl_name);
2497 /*This is to ensure we dont break targets which dont have the kernel change*/
2498 return true;
2499 }
2500 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2501 ALOGD("BT SOC status: %d",bt_soc_status);
2502 return bt_soc_status;
2503}
2504
Zhou Song331c8e52019-08-26 14:16:12 +08002505static int configure_btsco_sample_rate(snd_device_t snd_device)
2506{
2507 struct mixer_ctl *ctl = NULL;
2508 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2509 char *rate_str = NULL;
2510 bool is_rx_dev = true;
2511
2512 if (is_btsco_device(snd_device, snd_device)) {
2513 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2514 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2515 if (!ctl_sr_tx || !ctl_sr_rx) {
2516 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2517 if (!ctl_sr)
2518 return -ENOSYS;
2519 }
2520
2521 switch (snd_device) {
2522 case SND_DEVICE_OUT_BT_SCO:
2523 rate_str = "KHZ_8";
2524 break;
2525 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2526 case SND_DEVICE_IN_BT_SCO_MIC:
2527 rate_str = "KHZ_8";
2528 is_rx_dev = false;
2529 break;
2530 case SND_DEVICE_OUT_BT_SCO_WB:
2531 rate_str = "KHZ_16";
2532 break;
2533 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2534 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2535 rate_str = "KHZ_16";
2536 is_rx_dev = false;
2537 break;
2538 default:
2539 return 0;
2540 }
2541
2542 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2543 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2544 return -ENOSYS;
2545 }
2546 return 0;
2547}
2548
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302549int out_standby_l(struct audio_stream *stream);
2550
Eric Laurent637e2d42018-11-15 12:24:31 -08002551struct stream_in *adev_get_active_input(const struct audio_device *adev)
2552{
2553 struct listnode *node;
2554 struct stream_in *last_active_in = NULL;
2555
2556 /* Get last added active input.
2557 * TODO: We may use a priority mechanism to pick highest priority active source */
2558 list_for_each(node, &adev->usecase_list)
2559 {
2560 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2561 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2562 last_active_in = usecase->stream.in;
2563 }
2564
2565 return last_active_in;
2566}
2567
2568struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2569{
2570 struct listnode *node;
2571
2572 /* First check active inputs with voice communication source and then
2573 * any input if audio mode is in communication */
2574 list_for_each(node, &adev->usecase_list)
2575 {
2576 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2577 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2578 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2579 return usecase->stream.in;
2580 }
2581 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2582 return adev_get_active_input(adev);
2583
2584 return NULL;
2585}
2586
Carter Hsu2e429db2019-05-14 18:50:52 +08002587/*
2588 * Aligned with policy.h
2589 */
2590static inline int source_priority(int inputSource)
2591{
2592 switch (inputSource) {
2593 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2594 return 9;
2595 case AUDIO_SOURCE_CAMCORDER:
2596 return 8;
2597 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2598 return 7;
2599 case AUDIO_SOURCE_UNPROCESSED:
2600 return 6;
2601 case AUDIO_SOURCE_MIC:
2602 return 5;
2603 case AUDIO_SOURCE_ECHO_REFERENCE:
2604 return 4;
2605 case AUDIO_SOURCE_FM_TUNER:
2606 return 3;
2607 case AUDIO_SOURCE_VOICE_RECOGNITION:
2608 return 2;
2609 case AUDIO_SOURCE_HOTWORD:
2610 return 1;
2611 default:
2612 break;
2613 }
2614 return 0;
2615}
2616
2617static struct stream_in *get_priority_input(struct audio_device *adev)
2618{
2619 struct listnode *node;
2620 struct audio_usecase *usecase;
2621 int last_priority = 0, priority;
2622 struct stream_in *priority_in = NULL;
2623 struct stream_in *in;
2624
2625 list_for_each(node, &adev->usecase_list) {
2626 usecase = node_to_item(node, struct audio_usecase, list);
2627 if (usecase->type == PCM_CAPTURE) {
2628 in = usecase->stream.in;
2629 if (!in)
2630 continue;
2631 priority = source_priority(in->source);
2632
2633 if (priority > last_priority) {
2634 last_priority = priority;
2635 priority_in = in;
2636 }
2637 }
2638 }
2639 return priority_in;
2640}
2641
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002642int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002644 snd_device_t out_snd_device = SND_DEVICE_NONE;
2645 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002646 struct audio_usecase *usecase = NULL;
2647 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002648 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002649 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302650 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002651 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002652 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302654 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002656 usecase = get_usecase_from_list(adev, uc_id);
2657 if (usecase == NULL) {
2658 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2659 return -EINVAL;
2660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002662 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002663 (usecase->type == VOIP_CALL) ||
2664 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302665 if(usecase->stream.out == NULL) {
2666 ALOGE("%s: stream.out is NULL", __func__);
2667 return -EINVAL;
2668 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002669 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002670 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2671 uc_id);
2672 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2673 uc_id);
2674 } else {
2675 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302676 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002677 in_snd_device = platform_get_input_snd_device(adev->platform,
2678 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302679 &usecase->stream.out->device_list,
2680 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002681 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002682 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302683 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302684 if (usecase->stream.inout == NULL) {
2685 ALOGE("%s: stream.inout is NULL", __func__);
2686 return -EINVAL;
2687 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002688 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302689 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2690 stream_out.format = usecase->stream.inout->out_config.format;
2691 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302692 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002693 assign_devices(&usecase->device_list,
2694 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302695 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2696 if (usecase->stream.inout == NULL) {
2697 ALOGE("%s: stream.inout is NULL", __func__);
2698 return -EINVAL;
2699 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302700 struct listnode out_devices;
2701 list_init(&out_devices);
2702 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2703 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002704 assign_devices(&usecase->device_list,
2705 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002706 } else {
2707 /*
2708 * If the voice call is active, use the sound devices of voice call usecase
2709 * so that it would not result any device switch. All the usecases will
2710 * be switched to new device when select_devices() is called for voice call
2711 * usecase. This is to avoid switching devices for voice call when
2712 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002713 * choose voice call device only if the use case device is
2714 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002716 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002717 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002718 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002719 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2720 is_codec_backend_out_device_type(&usecase->device_list)) ||
2721 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2722 is_codec_backend_in_device_type(&usecase->device_list)) ||
2723 is_single_device_type_equal(&vc_usecase->device_list,
2724 AUDIO_DEVICE_OUT_HEARING_AID) ||
2725 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002726 AUDIO_DEVICE_IN_VOICE_CALL) ||
2727 (is_single_device_type_equal(&usecase->device_list,
2728 AUDIO_DEVICE_IN_USB_HEADSET) &&
2729 is_single_device_type_equal(&vc_usecase->device_list,
2730 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002731 in_snd_device = vc_usecase->in_snd_device;
2732 out_snd_device = vc_usecase->out_snd_device;
2733 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002734 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002735 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002736 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002737 if ((voip_usecase != NULL) &&
2738 (usecase->type == PCM_PLAYBACK) &&
2739 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002740 out_snd_device_backend_match = platform_check_backends_match(
2741 voip_usecase->out_snd_device,
2742 platform_get_output_snd_device(
2743 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302744 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002745 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002746 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2747 (is_codec_backend_out_device_type(&usecase->device_list) ||
2748 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002749 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002750 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002751 in_snd_device = voip_usecase->in_snd_device;
2752 out_snd_device = voip_usecase->out_snd_device;
2753 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002754 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002755 hfp_ucid = audio_extn_hfp_get_usecase();
2756 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002757 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002758 in_snd_device = hfp_usecase->in_snd_device;
2759 out_snd_device = hfp_usecase->out_snd_device;
2760 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002761 }
2762 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302763 if (usecase->stream.out == NULL) {
2764 ALOGE("%s: stream.out is NULL", __func__);
2765 return -EINVAL;
2766 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002767 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002768 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002769 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002770 struct stream_out *voip_out = adev->primary_output;
2771 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002772 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002773 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2774 else
2775 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302776 usecase->stream.out,
2777 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002778 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002779
Eric Laurent637e2d42018-11-15 12:24:31 -08002780 if (voip_usecase)
2781 voip_out = voip_usecase->stream.out;
2782
2783 if (usecase->stream.out == voip_out && voip_in != NULL)
2784 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002785 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002786 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302787 if (usecase->stream.in == NULL) {
2788 ALOGE("%s: stream.in is NULL", __func__);
2789 return -EINVAL;
2790 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002791 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002792 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002793 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002794 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002795 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002796 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002797
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002798 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002799 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002800 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2801 USECASE_AUDIO_PLAYBACK_VOIP);
2802
Carter Hsu2e429db2019-05-14 18:50:52 +08002803 usecase->stream.in->enable_ec_port = false;
2804
Zhou Song62ea0282020-03-22 19:53:01 +08002805 bool is_ha_usecase = adev->ha_proxy_enable ?
2806 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2807 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2808 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002809 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002810 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002811 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002812 } else if (adev->primary_output &&
2813 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 } else {
2816 /* forcing speaker o/p device to get matching i/p pair
2817 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002818 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002819 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002820 priority_in = voip_in;
2821 } else {
2822 /* get the input with the highest priority source*/
2823 priority_in = get_priority_input(adev);
2824
2825 if (!priority_in)
2826 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002827 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002828
Eric Laurent637e2d42018-11-15 12:24:31 -08002829 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002830 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302831 &out_devices,
2832 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002833 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002834 }
2835 }
2836
2837 if (out_snd_device == usecase->out_snd_device &&
2838 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302839
2840 if (!force_device_switch(usecase))
2841 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 }
2843
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002844 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002845 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002846 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002847 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2848 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302849 }
2850
Aalique Grahame22e49102018-12-18 14:23:57 -08002851 if (out_snd_device != SND_DEVICE_NONE &&
2852 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2853 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2854 __func__,
2855 use_case_table[uc_id],
2856 adev->last_logged_snd_device[uc_id][0],
2857 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2858 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2859 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2860 -1,
2861 out_snd_device,
2862 platform_get_snd_device_name(out_snd_device),
2863 platform_get_snd_device_acdb_id(out_snd_device));
2864 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2865 }
2866 if (in_snd_device != SND_DEVICE_NONE &&
2867 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2868 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2869 __func__,
2870 use_case_table[uc_id],
2871 adev->last_logged_snd_device[uc_id][1],
2872 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2873 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2874 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2875 -1,
2876 in_snd_device,
2877 platform_get_snd_device_name(in_snd_device),
2878 platform_get_snd_device_acdb_id(in_snd_device));
2879 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2880 }
2881
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 /*
2884 * Limitation: While in call, to do a device switch we need to disable
2885 * and enable both RX and TX devices though one of them is same as current
2886 * device.
2887 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002888 if ((usecase->type == VOICE_CALL) &&
2889 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2890 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002891 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002892 }
2893
2894 if (((usecase->type == VOICE_CALL) ||
2895 (usecase->type == VOIP_CALL)) &&
2896 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2897 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302898 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002899 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002900 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002901
2902 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302903 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002904 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002905 }
2906
Aalique Grahame22e49102018-12-18 14:23:57 -08002907 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2908 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002909 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302910 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002911 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2912 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2913 else
2914 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302915 }
2916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002917 /* Disable current sound devices */
2918 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002919 disable_audio_route(adev, usecase);
2920 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 }
2922
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002923 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002924 disable_audio_route(adev, usecase);
2925 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 }
2927
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002928 /* Applicable only on the targets that has external modem.
2929 * New device information should be sent to modem before enabling
2930 * the devices to reduce in-call device switch time.
2931 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002932 if ((usecase->type == VOICE_CALL) &&
2933 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2934 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002935 status = platform_switch_voice_call_enable_device_config(adev->platform,
2936 out_snd_device,
2937 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002938 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002940 /* Enable new sound devices */
2941 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002942 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302943 if (platform_check_codec_asrc_support(adev->platform))
2944 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002945 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 }
2947
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002948 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302949 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002950 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002951 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002952
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302953 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07002954 status = platform_switch_voice_call_device_post(adev->platform,
2955 out_snd_device,
2956 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002957
sangwoo170731f2013-06-08 15:36:36 +09002958 usecase->in_snd_device = in_snd_device;
2959 usecase->out_snd_device = out_snd_device;
2960
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302961 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2962 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302963 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002964 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002965 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002966 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2967 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2968 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2969 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2970 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2971 /*
2972 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2973 * configured device sample rate, if not update the COPP rate to be equal to the
2974 * device sample rate, else open COPP at stream sample rate
2975 */
2976 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2977 usecase->stream.out->sample_rate,
2978 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302979 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302980 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2981 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302982 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002983 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2984 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2985 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2986 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002987 }
2988 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002989
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002990 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002991
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002992 /* If input stream is already running then effect needs to be
2993 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002994 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002995 check_and_enable_effect(adev);
2996
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002997 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002998 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302999 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003000 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3001
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003002 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303003 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003004 voice_extn_compress_voip_is_started(adev))
3005 voice_set_sidetone(adev, out_snd_device, true);
3006 }
3007
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003008 /* Applicable only on the targets that has external modem.
3009 * Enable device command should be sent to modem only after
3010 * enabling voice call mixer controls
3011 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003012 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003013 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3014 out_snd_device,
3015 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303016
3017 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003018 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303019 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003020 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303021 if (is_bt_soc_on(adev) == false){
3022 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003023 if (in->pcm != NULL)
3024 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303025 }
3026 }
3027 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3028 && usecase->stream.out->started) {
3029 if (is_bt_soc_on(adev) == false) {
3030 ALOGD("BT SCO/A2DP disconnected while in connection");
3031 out_standby_l(&usecase->stream.out->stream.common);
3032 }
3033 }
3034 } else if ((usecase->stream.out != NULL) &&
3035 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303036 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3037 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003038 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303039 usecase->stream.out->started) {
3040 if (is_bt_soc_on(adev) == false) {
3041 ALOGD("BT SCO/A2dp disconnected while in connection");
3042 out_standby_l(&usecase->stream.out->stream.common);
3043 }
3044 }
3045 }
3046
Yung Ti Su70cb8242018-06-22 17:38:47 +08003047 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003048 struct stream_out *voip_out = voip_usecase->stream.out;
3049 audio_extn_utils_send_app_type_gain(adev,
3050 voip_out->app_type_cfg.app_type,
3051 &voip_out->app_type_cfg.gain[0]);
3052 }
3053
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303054 ALOGD("%s: done",__func__);
3055
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 return status;
3057}
3058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059static int stop_input_stream(struct stream_in *in)
3060{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303061 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303063
3064 if (in == NULL) {
3065 ALOGE("%s: stream_in ptr is NULL", __func__);
3066 return -EINVAL;
3067 }
3068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003070 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071
Eric Laurent994a6932013-07-17 11:51:42 -07003072 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003073 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 uc_info = get_usecase_from_list(adev, in->usecase);
3075 if (uc_info == NULL) {
3076 ALOGE("%s: Could not find the usecase (%d) in the list",
3077 __func__, in->usecase);
3078 return -EINVAL;
3079 }
3080
Carter Hsu2e429db2019-05-14 18:50:52 +08003081 priority_in = get_priority_input(adev);
3082
Derek Chenea197282019-01-07 17:35:01 -08003083 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3084 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003085
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003086 /* Close in-call recording streams */
3087 voice_check_and_stop_incall_rec_usecase(adev, in);
3088
Eric Laurent150dbfe2013-02-27 14:31:02 -08003089 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003090 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003091
3092 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003093 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003095 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303096 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3097
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003098 list_remove(&uc_info->list);
3099 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100
Carter Hsu2e429db2019-05-14 18:50:52 +08003101 if (priority_in == in) {
3102 priority_in = get_priority_input(adev);
3103 if (priority_in)
3104 select_devices(adev, priority_in->usecase);
3105 }
3106
Vatsal Buchac09ae062018-11-14 13:25:08 +05303107 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003108 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 return ret;
3110}
3111
3112int start_input_stream(struct stream_in *in)
3113{
3114 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003115 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303117
3118 if (in == NULL) {
3119 ALOGE("%s: stream_in ptr is NULL", __func__);
3120 return -EINVAL;
3121 }
3122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003124 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003125 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126
Mingming Yin2664a5b2015-09-03 10:53:11 -07003127 if (get_usecase_from_list(adev, usecase) == NULL)
3128 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303129 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3130 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003131
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303132 if (CARD_STATUS_OFFLINE == in->card_status||
3133 CARD_STATUS_OFFLINE == adev->card_status) {
3134 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303135 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303136 goto error_config;
3137 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303138
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003139 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303140 if (!adev->bt_sco_on) {
3141 ALOGE("%s: SCO profile is not ready, return error", __func__);
3142 ret = -EIO;
3143 goto error_config;
3144 }
3145 }
3146
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003147 /* Check if source matches incall recording usecase criteria */
3148 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3149 if (ret)
3150 goto error_config;
3151 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003152 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3153
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303154 if (audio_extn_cin_attached_usecase(in))
3155 audio_extn_cin_acquire_usecase(in);
3156
Mingming Yin2664a5b2015-09-03 10:53:11 -07003157 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3158 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3159 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003160 ret = -EINVAL;
3161 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003162 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003163
Eric Laurentb23d5282013-05-14 15:27:20 -07003164 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 if (in->pcm_device_id < 0) {
3166 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3167 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003168 ret = -EINVAL;
3169 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003173
3174 if (!uc_info) {
3175 ret = -ENOMEM;
3176 goto error_config;
3177 }
3178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 uc_info->id = in->usecase;
3180 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003181 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003182 list_init(&uc_info->device_list);
3183 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003184 uc_info->in_snd_device = SND_DEVICE_NONE;
3185 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003187 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003188 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303189 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3190 adev->perf_lock_opts,
3191 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003192 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193
Derek Chenea197282019-01-07 17:35:01 -08003194 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3195 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003196
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303197 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3198
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303199 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303200 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303201 if (ret)
3202 goto error_open;
3203 else
3204 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003205 }
3206
Haynes Mathew George16081042017-05-31 17:16:49 -07003207 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003208 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003209 ALOGE("%s: pcm stream not ready", __func__);
3210 goto error_open;
3211 }
3212 ret = pcm_start(in->pcm);
3213 if (ret < 0) {
3214 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3215 goto error_open;
3216 }
3217 } else {
3218 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3219 unsigned int pcm_open_retry_count = 0;
3220
Zhou Song62ea0282020-03-22 19:53:01 +08003221 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3222 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003223 flags |= PCM_MMAP | PCM_NOIRQ;
3224 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3225 } else if (in->realtime) {
3226 flags |= PCM_MMAP | PCM_NOIRQ;
3227 }
3228
Garmond Leunge2433c32017-09-28 21:51:22 -07003229 if (audio_extn_ffv_get_stream() == in) {
3230 ALOGD("%s: ffv stream, update pcm config", __func__);
3231 audio_extn_ffv_update_pcm_config(&config);
3232 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003233 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3234 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3235
3236 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003237 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003238 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003239 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003240 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303241 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303242 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3243 adev->card_status = CARD_STATUS_OFFLINE;
3244 in->card_status = CARD_STATUS_OFFLINE;
3245 ret = -EIO;
3246 goto error_open;
3247 }
3248
Haynes Mathew George16081042017-05-31 17:16:49 -07003249 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3250 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3251 if (in->pcm != NULL) {
3252 pcm_close(in->pcm);
3253 in->pcm = NULL;
3254 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003255 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003256 ret = -EIO;
3257 goto error_open;
3258 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003259 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003260 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3261 continue;
3262 }
3263 break;
3264 }
3265
3266 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003267 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003268 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003269 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003270 if (ret < 0) {
3271 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3272 pcm_close(in->pcm);
3273 in->pcm = NULL;
3274 goto error_open;
3275 }
3276 register_in_stream(in);
3277 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003278 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003279 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003280 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003281 if (ret < 0) {
3282 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003283 pcm_close(in->pcm);
3284 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003285 goto error_open;
3286 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003287 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003288 }
3289
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003290 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003291 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3292 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003293
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003294 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303295 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3296
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303297done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003298 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303299 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003300 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303301 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003302 return ret;
3303
3304error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003305 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303306 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003308
Eric Laurentc8400632013-02-14 19:04:54 -08003309error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003310 if (audio_extn_cin_attached_usecase(in))
3311 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303312 /*
3313 * sleep 50ms to allow sufficient time for kernel
3314 * drivers to recover incases like SSR.
3315 */
3316 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003317 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303318 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320}
3321
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003322void lock_input_stream(struct stream_in *in)
3323{
3324 pthread_mutex_lock(&in->pre_lock);
3325 pthread_mutex_lock(&in->lock);
3326 pthread_mutex_unlock(&in->pre_lock);
3327}
3328
3329void lock_output_stream(struct stream_out *out)
3330{
3331 pthread_mutex_lock(&out->pre_lock);
3332 pthread_mutex_lock(&out->lock);
3333 pthread_mutex_unlock(&out->pre_lock);
3334}
3335
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003336/* must be called with out->lock locked */
3337static int send_offload_cmd_l(struct stream_out* out, int command)
3338{
3339 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3340
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003341 if (!cmd) {
3342 ALOGE("failed to allocate mem for command 0x%x", command);
3343 return -ENOMEM;
3344 }
3345
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 ALOGVV("%s %d", __func__, command);
3347
3348 cmd->cmd = command;
3349 list_add_tail(&out->offload_cmd_list, &cmd->node);
3350 pthread_cond_signal(&out->offload_cond);
3351 return 0;
3352}
3353
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003354/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355static void stop_compressed_output_l(struct stream_out *out)
3356{
3357 out->offload_state = OFFLOAD_STATE_IDLE;
3358 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003359 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 if (out->compr != NULL) {
3361 compress_stop(out->compr);
3362 while (out->offload_thread_blocked) {
3363 pthread_cond_wait(&out->cond, &out->lock);
3364 }
3365 }
3366}
3367
Varun Balaraje49253e2017-07-06 19:48:56 +05303368bool is_interactive_usecase(audio_usecase_t uc_id)
3369{
3370 unsigned int i;
3371 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3372 if (uc_id == interactive_usecases[i])
3373 return true;
3374 }
3375 return false;
3376}
3377
3378static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3379{
3380 audio_usecase_t ret_uc = USECASE_INVALID;
3381 unsigned int intract_uc_index;
3382 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3383
3384 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3385 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3386 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3387 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3388 ret_uc = interactive_usecases[intract_uc_index];
3389 break;
3390 }
3391 }
3392
3393 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3394 return ret_uc;
3395}
3396
3397static void free_interactive_usecase(struct audio_device *adev,
3398 audio_usecase_t uc_id)
3399{
3400 unsigned int interact_uc_index;
3401 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3402
3403 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3404 if (interactive_usecases[interact_uc_index] == uc_id) {
3405 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3406 break;
3407 }
3408 }
3409 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3410}
3411
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003412bool is_offload_usecase(audio_usecase_t uc_id)
3413{
3414 unsigned int i;
3415 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3416 if (uc_id == offload_usecases[i])
3417 return true;
3418 }
3419 return false;
3420}
3421
Dhananjay Kumarac341582017-02-23 23:42:25 +05303422static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003423{
vivek mehta446c3962015-09-14 10:57:35 -07003424 audio_usecase_t ret_uc = USECASE_INVALID;
3425 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003426 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003427 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303428 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003429 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3430 else
3431 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003432
vivek mehta446c3962015-09-14 10:57:35 -07003433 pthread_mutex_lock(&adev->lock);
3434 if (get_usecase_from_list(adev, ret_uc) != NULL)
3435 ret_uc = USECASE_INVALID;
3436 pthread_mutex_unlock(&adev->lock);
3437
3438 return ret_uc;
3439 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003440
3441 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003442 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3443 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3444 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3445 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003446 break;
3447 }
3448 }
vivek mehta446c3962015-09-14 10:57:35 -07003449
3450 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3451 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003452}
3453
3454static void free_offload_usecase(struct audio_device *adev,
3455 audio_usecase_t uc_id)
3456{
vivek mehta446c3962015-09-14 10:57:35 -07003457 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003458 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003459
3460 if (!adev->multi_offload_enable)
3461 return;
3462
3463 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3464 if (offload_usecases[offload_uc_index] == uc_id) {
3465 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003466 break;
3467 }
3468 }
3469 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3470}
3471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003472static void *offload_thread_loop(void *context)
3473{
3474 struct stream_out *out = (struct stream_out *) context;
3475 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003476 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003478 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003479 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003480 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3481
3482 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003483 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003484 out->offload_state = OFFLOAD_STATE_IDLE;
3485 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 for (;;) {
3487 struct offload_cmd *cmd = NULL;
3488 stream_callback_event_t event;
3489 bool send_callback = false;
3490
3491 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3492 __func__, list_empty(&out->offload_cmd_list),
3493 out->offload_state);
3494 if (list_empty(&out->offload_cmd_list)) {
3495 ALOGV("%s SLEEPING", __func__);
3496 pthread_cond_wait(&out->offload_cond, &out->lock);
3497 ALOGV("%s RUNNING", __func__);
3498 continue;
3499 }
3500
3501 item = list_head(&out->offload_cmd_list);
3502 cmd = node_to_item(item, struct offload_cmd, node);
3503 list_remove(item);
3504
3505 ALOGVV("%s STATE %d CMD %d out->compr %p",
3506 __func__, out->offload_state, cmd->cmd, out->compr);
3507
3508 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3509 free(cmd);
3510 break;
3511 }
3512
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003513 // allow OFFLOAD_CMD_ERROR reporting during standby
3514 // this is needed to handle failures during compress_open
3515 // Note however that on a pause timeout, the stream is closed
3516 // and no offload usecase will be active. Therefore this
3517 // special case is needed for compress_open failures alone
3518 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3519 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003520 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003521 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 pthread_cond_signal(&out->cond);
3523 continue;
3524 }
3525 out->offload_thread_blocked = true;
3526 pthread_mutex_unlock(&out->lock);
3527 send_callback = false;
3528 switch(cmd->cmd) {
3529 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003530 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003531 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003532 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003533 send_callback = true;
3534 event = STREAM_CBK_EVENT_WRITE_READY;
3535 break;
3536 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003537 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303538 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003539 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303540 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003541 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303542 if (ret < 0)
3543 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303544 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303545 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003546 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003547 else
3548 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003549 if (-ENETRESET != ret && !(-EINTR == ret &&
3550 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303551 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303552 pthread_mutex_lock(&out->lock);
3553 out->send_new_metadata = 1;
3554 out->send_next_track_params = true;
3555 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303556 event = STREAM_CBK_EVENT_DRAIN_READY;
3557 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3558 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303559 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 break;
3561 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003562 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003563 ret = compress_drain(out->compr);
3564 ALOGD("copl(%p):out of compress_drain", out);
3565 // EINTR check avoids drain interruption due to SSR
3566 if (-ENETRESET != ret && !(-EINTR == ret &&
3567 CARD_STATUS_OFFLINE == out->card_status)) {
3568 send_callback = true;
3569 event = STREAM_CBK_EVENT_DRAIN_READY;
3570 } else
3571 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003572 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303573 case OFFLOAD_CMD_ERROR:
3574 ALOGD("copl(%p): sending error callback to AF", out);
3575 send_callback = true;
3576 event = STREAM_CBK_EVENT_ERROR;
3577 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 default:
3579 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3580 break;
3581 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003582 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 out->offload_thread_blocked = false;
3584 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003585 if (send_callback && out->client_callback) {
3586 ALOGVV("%s: sending client_callback event %d", __func__, event);
3587 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003588 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003589 free(cmd);
3590 }
3591
3592 pthread_cond_signal(&out->cond);
3593 while (!list_empty(&out->offload_cmd_list)) {
3594 item = list_head(&out->offload_cmd_list);
3595 list_remove(item);
3596 free(node_to_item(item, struct offload_cmd, node));
3597 }
3598 pthread_mutex_unlock(&out->lock);
3599
3600 return NULL;
3601}
3602
3603static int create_offload_callback_thread(struct stream_out *out)
3604{
3605 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3606 list_init(&out->offload_cmd_list);
3607 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3608 offload_thread_loop, out);
3609 return 0;
3610}
3611
3612static int destroy_offload_callback_thread(struct stream_out *out)
3613{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003614 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003615 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003616 stop_compressed_output_l(out);
3617 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3618
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003619 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003620 pthread_mutex_unlock(&out->lock);
3621 pthread_join(out->offload_thread, (void **) NULL);
3622 pthread_cond_destroy(&out->offload_cond);
3623
3624 return 0;
3625}
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627static int stop_output_stream(struct stream_out *out)
3628{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303629 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 struct audio_usecase *uc_info;
3631 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003632 bool has_voip_usecase =
3633 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634
Eric Laurent994a6932013-07-17 11:51:42 -07003635 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003636 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 uc_info = get_usecase_from_list(adev, out->usecase);
3638 if (uc_info == NULL) {
3639 ALOGE("%s: Could not find the usecase (%d) in the list",
3640 __func__, out->usecase);
3641 return -EINVAL;
3642 }
3643
Derek Chenea197282019-01-07 17:35:01 -08003644 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3645 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003646
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003647 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303648 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003649 if (adev->visualizer_stop_output != NULL)
3650 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003651
3652 audio_extn_dts_remove_state_notifier_node(out->usecase);
3653
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003654 if (adev->offload_effects_stop_output != NULL)
3655 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003656 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3657 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3658 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003659 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003660
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003661 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3662 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003663 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003664 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003665
Eric Laurent150dbfe2013-02-27 14:31:02 -08003666 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003667 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003668
3669 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003670 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
Aalique Grahame22e49102018-12-18 14:23:57 -08003672 audio_extn_extspk_update(adev->extspk);
3673
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003674 if (is_offload_usecase(out->usecase)) {
3675 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3676 adev->dsp_bit_width_enforce_mode,
3677 false);
3678 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003679 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003680 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3681 false);
3682
3683 if (ret != 0)
3684 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3685 /* default service interval was successfully updated,
3686 reopen USB backend with new service interval */
3687 ret = 0;
3688 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003689
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003690 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303691 out->started = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003692 pthread_mutex_lock(&out->latch_lock);
3693 out->muted = false;
3694 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003695 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303696 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003697 ALOGV("Disable passthrough , reset mixer to pcm");
3698 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003699#ifdef AUDIO_GKI_ENABLED
3700 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3701 out->compr_config.codec->reserved[0] = 0;
3702#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003703 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003704#endif
Mingming Yin21854652016-04-13 11:54:02 -07003705 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003706 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3707 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003708
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303709 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003710 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303711 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303712
Manish Dewangan21a850a2017-08-14 12:03:55 +05303713 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003714 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3715 if (ret < 0)
3716 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3717 }
3718
juyuchen2d415992018-11-16 14:15:16 +08003719 /* 1) media + voip output routing to handset must route media back to
3720 speaker when voip stops.
3721 2) trigger voip input to reroute when voip output changes to
3722 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003723 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003724 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003725 struct listnode *node;
3726 struct audio_usecase *usecase;
3727 list_for_each(node, &adev->usecase_list) {
3728 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003729 if ((usecase->type == PCM_CAPTURE &&
3730 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3731 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003732 continue;
3733
3734 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3735 __func__, usecase->id, use_case_table[usecase->id],
3736 out->usecase, use_case_table[out->usecase]);
3737 select_devices(adev, usecase->id);
3738 }
3739 }
3740
Garmond Leung5fd0b552018-04-17 11:56:12 -07003741 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003742 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 return ret;
3744}
3745
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003746struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3747 unsigned int flags, unsigned int pcm_open_retry_count,
3748 struct pcm_config *config)
3749{
3750 struct pcm* pcm = NULL;
3751
3752 while (1) {
3753 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3754 if (pcm == NULL || !pcm_is_ready(pcm)) {
3755 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3756 if (pcm != NULL) {
3757 pcm_close(pcm);
3758 pcm = NULL;
3759 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003760 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003761 return NULL;
3762
Weiyin Jiang72197252019-10-09 11:49:32 +08003763 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003764 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3765 continue;
3766 }
3767 break;
3768 }
3769
3770 if (pcm_is_ready(pcm)) {
3771 int ret = pcm_prepare(pcm);
3772 if (ret < 0) {
3773 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3774 pcm_close(pcm);
3775 pcm = NULL;
3776 }
3777 }
3778
3779 return pcm;
3780}
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782int start_output_stream(struct stream_out *out)
3783{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 struct audio_usecase *uc_info;
3786 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003787 char mixer_ctl_name[128];
3788 struct mixer_ctl *ctl = NULL;
3789 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303790 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003791 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792
Haynes Mathew George380745d2017-10-04 15:27:45 -07003793 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003794 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3795 ret = -EINVAL;
3796 goto error_config;
3797 }
3798
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003799 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303800 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003801 get_device_types(&out->device_list), is_haptic_usecase);
3802
3803 bool is_speaker_active = compare_device_type(&out->device_list,
3804 AUDIO_DEVICE_OUT_SPEAKER);
3805 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3806 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303807
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303808 if (CARD_STATUS_OFFLINE == out->card_status ||
3809 CARD_STATUS_OFFLINE == adev->card_status) {
3810 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303811 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003812 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303813 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303814
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003815 //Update incall music usecase to reflect correct voice session
3816 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3817 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3818 if (ret != 0) {
3819 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3820 __func__, ret);
3821 goto error_config;
3822 }
3823 }
3824
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003825 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003826 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003827 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303828 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303829 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303830 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3831 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3832 ret = -EAGAIN;
3833 goto error_config;
3834 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303835 }
3836 }
3837 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003838 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303839 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003840 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303841 //combo usecase just by pass a2dp
3842 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003843 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303844 } else {
3845 ALOGE("%s: SCO profile is not ready, return error", __func__);
3846 ret = -EAGAIN;
3847 goto error_config;
3848 }
3849 }
3850 }
3851
Eric Laurentb23d5282013-05-14 15:27:20 -07003852 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 if (out->pcm_device_id < 0) {
3854 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3855 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003856 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003857 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 }
3859
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003860 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003861 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3862 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003863 if (adev->haptic_pcm_device_id < 0) {
3864 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3865 __func__, adev->haptic_pcm_device_id, out->usecase);
3866 ret = -EINVAL;
3867 goto error_config;
3868 }
3869 }
3870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003872
3873 if (!uc_info) {
3874 ret = -ENOMEM;
3875 goto error_config;
3876 }
3877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 uc_info->id = out->usecase;
3879 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003880 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003881 list_init(&uc_info->device_list);
3882 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003883 uc_info->in_snd_device = SND_DEVICE_NONE;
3884 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003885
3886 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003887 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003888 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3889 /* USB backend is not reopened immediately.
3890 This is eventually done as part of select_devices */
3891 }
3892
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003893 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894
Wei Wangf7ca6c92017-11-21 14:51:20 -08003895 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303896 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3897 adev->perf_lock_opts,
3898 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303899
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003900 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303901 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303902 if (audio_extn_passthru_is_enabled() &&
3903 audio_extn_passthru_is_passthrough_stream(out)) {
3904 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303905 }
3906 }
3907
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003908 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003909 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303910 if (!a2dp_combo) {
3911 check_a2dp_restore_l(adev, out, false);
3912 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003913 struct listnode dev;
3914 list_init(&dev);
3915 assign_devices(&dev, &out->device_list);
3916 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3917 reassign_device_list(&out->device_list,
3918 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003919 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003920 reassign_device_list(&out->device_list,
3921 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303922 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003923 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303924 }
3925 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303926 select_devices(adev, out->usecase);
3927 if (is_a2dp_out_device_type(&out->device_list) &&
3928 !adev->a2dp_started) {
3929 if (is_speaker_active || is_speaker_safe_active) {
3930 struct listnode dev;
3931 list_init(&dev);
3932 assign_devices(&dev, &out->device_list);
3933 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3934 reassign_device_list(&out->device_list,
3935 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3936 else
3937 reassign_device_list(&out->device_list,
3938 AUDIO_DEVICE_OUT_SPEAKER, "");
3939 select_devices(adev, out->usecase);
3940 assign_devices(&out->device_list, &dev);
3941 } else {
3942 ret = -EINVAL;
3943 goto error_open;
3944 }
3945 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303946 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003947
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003948 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3949 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003950 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003951 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003952
Derek Chenea197282019-01-07 17:35:01 -08003953 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3954 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003955
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003956 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3957 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003958
3959 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003960 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003961 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3962 ALOGE("%s: pcm stream not ready", __func__);
3963 goto error_open;
3964 }
3965 ret = pcm_start(out->pcm);
3966 if (ret < 0) {
3967 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3968 goto error_open;
3969 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003970 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003971 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003972 unsigned int flags = PCM_OUT;
3973 unsigned int pcm_open_retry_count = 0;
3974 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3975 flags |= PCM_MMAP | PCM_NOIRQ;
3976 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003977 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003978 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003979 } else
3980 flags |= PCM_MONOTONIC;
3981
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003982 if ((adev->vr_audio_mode_enabled) &&
3983 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3984 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3985 "PCM_Dev %d Topology", out->pcm_device_id);
3986 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3987 if (!ctl) {
3988 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3989 __func__, mixer_ctl_name);
3990 } else {
3991 //if success use ULLPP
3992 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3993 __func__, mixer_ctl_name, out->pcm_device_id);
3994 //There is a still a possibility that some sessions
3995 // that request for FAST|RAW when 3D audio is active
3996 //can go through ULLPP. Ideally we expects apps to
3997 //listen to audio focus and stop concurrent playback
3998 //Also, we will look for mode flag (voice_in_communication)
3999 //before enabling the realtime flag.
4000 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4001 }
4002 }
4003
Surendar Karka91fa3682018-07-02 18:12:12 +05304004 if (out->realtime)
4005 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4006 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4007
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004008 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4009 flags, pcm_open_retry_count,
4010 &(out->config));
4011 if (out->pcm == NULL) {
4012 ret = -EIO;
4013 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004014 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004015
4016 if (is_haptic_usecase) {
4017 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4018 adev->haptic_pcm_device_id,
4019 flags, pcm_open_retry_count,
4020 &(adev->haptics_config));
4021 // failure to open haptics pcm shouldnt stop audio,
4022 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004023
4024 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4025 ALOGD("%s: enable haptic audio synchronization", __func__);
4026 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4027 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004028 }
4029
Surendar Karka91fa3682018-07-02 18:12:12 +05304030 if (!out->realtime)
4031 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304032 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004033
Zhou Song2b8f28f2017-09-11 10:51:38 +08004034 // apply volume for voip playback after path is set up
4035 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4036 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304037 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4038 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304039 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4040 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004041 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4042 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304043 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004045 /*
4046 * set custom channel map if:
4047 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4048 * 2. custom channel map has been set by client
4049 * else default channel map of FC/FR/FL can always be set to DSP
4050 */
4051 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4052 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4053 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004054 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4055 adev->dsp_bit_width_enforce_mode,
4056 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004058 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004059 out->compr = compress_open(adev->snd_card,
4060 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004062 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304063 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304064 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4065 adev->card_status = CARD_STATUS_OFFLINE;
4066 out->card_status = CARD_STATUS_OFFLINE;
4067 ret = -EIO;
4068 goto error_open;
4069 }
4070
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004071 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004072 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004073 compress_close(out->compr);
4074 out->compr = NULL;
4075 ret = -EIO;
4076 goto error_open;
4077 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304078 /* compress_open sends params of the track, so reset the flag here */
4079 out->is_compr_metadata_avail = false;
4080
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004081 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004082 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004083
Fred Oh3f43e742015-03-04 18:42:34 -08004084 /* Since small bufs uses blocking writes, a write will be blocked
4085 for the default max poll time (20s) in the event of an SSR.
4086 Reduce the poll time to observe and deal with SSR faster.
4087 */
Ashish Jain5106d362016-05-11 19:23:33 +05304088 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004089 compress_set_max_poll_wait(out->compr, 1000);
4090 }
4091
Manish Dewangan69426c82017-01-30 17:35:36 +05304092 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304093 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304094
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004095 audio_extn_dts_create_state_notifier_node(out->usecase);
4096 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4097 popcount(out->channel_mask),
4098 out->playback_started);
4099
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004100#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304101 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004102 audio_extn_dolby_send_ddp_endp_params(adev);
4103#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304104 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4105 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004106 if (adev->visualizer_start_output != NULL)
4107 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4108 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304109 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004110 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004111 }
Derek Chenf13dd492018-11-13 14:53:51 -08004112
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004113 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004114 /* Update cached volume from media to offload/direct stream */
4115 struct listnode *node = NULL;
4116 list_for_each(node, &adev->active_outputs_list) {
4117 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4118 streams_output_ctxt_t,
4119 list);
4120 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4121 out->volume_l = out_ctxt->output->volume_l;
4122 out->volume_r = out_ctxt->output->volume_r;
4123 }
4124 }
4125 out_set_compr_volume(&out->stream,
4126 out->volume_l, out->volume_r);
4127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004129
4130 if (ret == 0) {
4131 register_out_stream(out);
4132 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004133 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4134 ALOGE("%s: pcm stream not ready", __func__);
4135 goto error_open;
4136 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004137 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004138 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004139 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004140 if (ret < 0)
4141 goto error_open;
4142 }
4143 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004144 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304145 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004146 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004147
vivek mehtad15d2bf2019-05-17 13:35:10 -07004148 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4149 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4150 audio_low_latency_hint_start();
4151 }
4152
Manish Dewangan21a850a2017-08-14 12:03:55 +05304153 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004154 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004155 if (ret < 0)
4156 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4157 }
4158
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004159 // consider a scenario where on pause lower layers are tear down.
4160 // so on resume, swap mixer control need to be sent only when
4161 // backend is active, hence rather than sending from enable device
4162 // sending it from start of streamtream
4163
4164 platform_set_swap_channels(adev, true);
4165
Haynes Mathew George380745d2017-10-04 15:27:45 -07004166 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304167 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004168 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004169error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004170 if (adev->haptic_pcm) {
4171 pcm_close(adev->haptic_pcm);
4172 adev->haptic_pcm = NULL;
4173 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004174 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304175 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004177error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304178 /*
4179 * sleep 50ms to allow sufficient time for kernel
4180 * drivers to recover incases like SSR.
4181 */
4182 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004183error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004184 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304185 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187}
4188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189static int check_input_parameters(uint32_t sample_rate,
4190 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004191 int channel_count,
4192 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004194 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304196 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4197 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4198 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004199 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004200 !audio_extn_compr_cap_format_supported(format) &&
4201 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004202 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004203
Aalique Grahame22e49102018-12-18 14:23:57 -08004204 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4205 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4206 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4207 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4208 return -EINVAL;
4209 }
4210
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004211 switch (channel_count) {
4212 case 1:
4213 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304214 case 3:
4215 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004216 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004217 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304218 case 10:
4219 case 12:
4220 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004221 break;
4222 default:
4223 ret = -EINVAL;
4224 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225
4226 switch (sample_rate) {
4227 case 8000:
4228 case 11025:
4229 case 12000:
4230 case 16000:
4231 case 22050:
4232 case 24000:
4233 case 32000:
4234 case 44100:
4235 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004236 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304237 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004238 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304239 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240 break;
4241 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004242 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 }
4244
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004245 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246}
4247
Naresh Tanniru04f71882018-06-26 17:46:22 +05304248
4249/** Add a value in a list if not already present.
4250 * @return true if value was successfully inserted or already present,
4251 * false if the list is full and does not contain the value.
4252 */
4253static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4254 for (size_t i = 0; i < list_length; i++) {
4255 if (list[i] == value) return true; // value is already present
4256 if (list[i] == 0) { // no values in this slot
4257 list[i] = value;
4258 return true; // value inserted
4259 }
4260 }
4261 return false; // could not insert value
4262}
4263
4264/** Add channel_mask in supported_channel_masks if not already present.
4265 * @return true if channel_mask was successfully inserted or already present,
4266 * false if supported_channel_masks is full and does not contain channel_mask.
4267 */
4268static void register_channel_mask(audio_channel_mask_t channel_mask,
4269 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4270 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4271 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4272}
4273
4274/** Add format in supported_formats if not already present.
4275 * @return true if format was successfully inserted or already present,
4276 * false if supported_formats is full and does not contain format.
4277 */
4278static void register_format(audio_format_t format,
4279 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4280 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4281 "%s: stream can not declare supporting its format %x", __func__, format);
4282}
4283/** Add sample_rate in supported_sample_rates if not already present.
4284 * @return true if sample_rate was successfully inserted or already present,
4285 * false if supported_sample_rates is full and does not contain sample_rate.
4286 */
4287static void register_sample_rate(uint32_t sample_rate,
4288 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4289 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4290 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4291}
4292
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004293static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4294{
4295 uint32_t high = num1, low = num2, temp = 0;
4296
4297 if (!num1 || !num2)
4298 return 0;
4299
4300 if (num1 < num2) {
4301 high = num2;
4302 low = num1;
4303 }
4304
4305 while (low != 0) {
4306 temp = low;
4307 low = high % low;
4308 high = temp;
4309 }
4310 return (num1 * num2)/high;
4311}
4312
4313static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4314{
4315 uint32_t remainder = 0;
4316
4317 if (!multiplier)
4318 return num;
4319
4320 remainder = num % multiplier;
4321 if (remainder)
4322 num += (multiplier - remainder);
4323
4324 return num;
4325}
4326
Aalique Grahame22e49102018-12-18 14:23:57 -08004327static size_t get_stream_buffer_size(size_t duration_ms,
4328 uint32_t sample_rate,
4329 audio_format_t format,
4330 int channel_count,
4331 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332{
4333 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004334 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335
Aalique Grahame22e49102018-12-18 14:23:57 -08004336 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004337 if (is_low_latency)
4338 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304339
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004340 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004341 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342
Ralf Herzbd08d632018-09-28 15:50:49 +02004343 /* make sure the size is multiple of 32 bytes and additionally multiple of
4344 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004345 * At 48 kHz mono 16-bit PCM:
4346 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4347 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004348 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004349 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004350 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004351
4352 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353}
4354
Aalique Grahame22e49102018-12-18 14:23:57 -08004355static size_t get_input_buffer_size(uint32_t sample_rate,
4356 audio_format_t format,
4357 int channel_count,
4358 bool is_low_latency)
4359{
4360 /* Don't know if USB HIFI in this context so use true to be conservative */
4361 if (check_input_parameters(sample_rate, format, channel_count,
4362 true /*is_usb_hifi */) != 0)
4363 return 0;
4364
4365 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4366 sample_rate,
4367 format,
4368 channel_count,
4369 is_low_latency);
4370}
4371
Derek Chenf6318be2017-06-12 17:16:24 -04004372size_t get_output_period_size(uint32_t sample_rate,
4373 audio_format_t format,
4374 int channel_count,
4375 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304376{
4377 size_t size = 0;
4378 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4379
4380 if ((duration == 0) || (sample_rate == 0) ||
4381 (bytes_per_sample == 0) || (channel_count == 0)) {
4382 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4383 bytes_per_sample, channel_count);
4384 return -EINVAL;
4385 }
4386
4387 size = (sample_rate *
4388 duration *
4389 bytes_per_sample *
4390 channel_count) / 1000;
4391 /*
4392 * To have same PCM samples for all channels, the buffer size requires to
4393 * be multiple of (number of channels * bytes per sample)
4394 * For writes to succeed, the buffer must be written at address which is multiple of 32
4395 */
4396 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4397
4398 return (size/(channel_count * bytes_per_sample));
4399}
4400
Zhou Song48453a02018-01-10 17:50:59 +08004401static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304402{
4403 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004404 uint64_t written_frames = 0;
4405 uint64_t kernel_frames = 0;
4406 uint64_t dsp_frames = 0;
4407 uint64_t signed_frames = 0;
4408 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304409
4410 /* This adjustment accounts for buffering after app processor.
4411 * It is based on estimated DSP latency per use case, rather than exact.
4412 */
George Gao9ba8a142020-07-23 14:30:03 -07004413 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004414 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304415
Zhou Song48453a02018-01-10 17:50:59 +08004416 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004417 written_frames = out->written /
4418 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4419
Ashish Jain5106d362016-05-11 19:23:33 +05304420 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4421 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4422 * hence only estimate.
4423 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004424 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4425 kernel_frames = kernel_buffer_size /
4426 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304427
Weiyin Jiang4813da12020-05-28 00:37:28 +08004428 if (written_frames >= (kernel_frames + dsp_frames))
4429 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304430
Zhou Song48453a02018-01-10 17:50:59 +08004431 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304432 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004433 if (timestamp != NULL )
4434 *timestamp = out->writeAt;
4435 } else if (timestamp != NULL) {
4436 clock_gettime(CLOCK_MONOTONIC, timestamp);
4437 }
4438 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304439
Weiyin Jiang4813da12020-05-28 00:37:28 +08004440 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4441 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304442
4443 return actual_frames_rendered;
4444}
4445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4447{
4448 struct stream_out *out = (struct stream_out *)stream;
4449
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004450 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451}
4452
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004453static int out_set_sample_rate(struct audio_stream *stream __unused,
4454 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455{
4456 return -ENOSYS;
4457}
4458
4459static size_t out_get_buffer_size(const struct audio_stream *stream)
4460{
4461 struct stream_out *out = (struct stream_out *)stream;
4462
Varun Balaraje49253e2017-07-06 19:48:56 +05304463 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304464 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304465 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304466 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4467 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4468 else
4469 return out->compr_config.fragment_size;
4470 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004471 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304472 else if (is_offload_usecase(out->usecase) &&
4473 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304474 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004475
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004476 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004477 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478}
4479
4480static uint32_t out_get_channels(const struct audio_stream *stream)
4481{
4482 struct stream_out *out = (struct stream_out *)stream;
4483
4484 return out->channel_mask;
4485}
4486
4487static audio_format_t out_get_format(const struct audio_stream *stream)
4488{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004489 struct stream_out *out = (struct stream_out *)stream;
4490
4491 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492}
4493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004494static int out_set_format(struct audio_stream *stream __unused,
4495 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496{
4497 return -ENOSYS;
4498}
4499
4500static int out_standby(struct audio_stream *stream)
4501{
4502 struct stream_out *out = (struct stream_out *)stream;
4503 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004504 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004505
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304506 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4507 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004509 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004511 if (adev->adm_deregister_stream)
4512 adev->adm_deregister_stream(adev->adm_data, out->handle);
4513
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004514 if (is_offload_usecase(out->usecase)) {
4515 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004516 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004517 pthread_mutex_unlock(&out->latch_lock);
4518 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004519
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004520 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004522 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4523 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304524 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004525 pthread_mutex_unlock(&adev->lock);
4526 pthread_mutex_unlock(&out->lock);
4527 ALOGD("VOIP output entered standby");
4528 return 0;
4529 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004530 if (out->pcm) {
4531 pcm_close(out->pcm);
4532 out->pcm = NULL;
4533 }
Meng Wanga09da002020-04-20 12:56:04 +08004534 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4535 if (adev->haptic_pcm) {
4536 pcm_close(adev->haptic_pcm);
4537 adev->haptic_pcm = NULL;
4538 }
4539
4540 if (adev->haptic_buffer != NULL) {
4541 free(adev->haptic_buffer);
4542 adev->haptic_buffer = NULL;
4543 adev->haptic_buffer_size = 0;
4544 }
4545 adev->haptic_pcm_device_id = 0;
4546 }
4547
Haynes Mathew George16081042017-05-31 17:16:49 -07004548 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4549 do_stop = out->playback_started;
4550 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004551
4552 if (out->mmap_shared_memory_fd >= 0) {
4553 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4554 __func__, out->mmap_shared_memory_fd);
4555 close(out->mmap_shared_memory_fd);
4556 out->mmap_shared_memory_fd = -1;
4557 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004558 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004559 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004560 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304561 out->send_next_track_params = false;
4562 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004563 out->gapless_mdata.encoder_delay = 0;
4564 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004565 if (out->compr != NULL) {
4566 compress_close(out->compr);
4567 out->compr = NULL;
4568 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004569 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004570 if (do_stop) {
4571 stop_output_stream(out);
4572 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304573 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004574 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004575 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 }
4577 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304578 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 return 0;
4580}
4581
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304582static int out_on_error(struct audio_stream *stream)
4583{
4584 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004585 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304586
4587 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004588 // always send CMD_ERROR for offload streams, this
4589 // is needed e.g. when SSR happens within compress_open
4590 // since the stream is active, offload_callback_thread is also active.
4591 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004592 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004593 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004594 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004595 }
4596 pthread_mutex_unlock(&out->lock);
4597
4598 status = out_standby(&out->stream.common);
4599
4600 lock_output_stream(out);
4601 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004602 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304603 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304604
4605 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4606 ALOGD("Setting previous card status if offline");
4607 out->prev_card_status_offline = true;
4608 }
4609
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304610 pthread_mutex_unlock(&out->lock);
4611
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004612 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304613}
4614
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304615/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004616 * standby implementation without locks, assumes that the callee already
4617 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304618 */
4619int out_standby_l(struct audio_stream *stream)
4620{
4621 struct stream_out *out = (struct stream_out *)stream;
4622 struct audio_device *adev = out->dev;
4623
4624 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4625 stream, out->usecase, use_case_table[out->usecase]);
4626
4627 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004628 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304629 if (adev->adm_deregister_stream)
4630 adev->adm_deregister_stream(adev->adm_data, out->handle);
4631
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004632 if (is_offload_usecase(out->usecase)) {
4633 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304634 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004635 pthread_mutex_unlock(&out->latch_lock);
4636 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304637
4638 out->standby = true;
4639 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4640 voice_extn_compress_voip_close_output_stream(stream);
4641 out->started = 0;
4642 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004643 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304644 return 0;
4645 } else if (!is_offload_usecase(out->usecase)) {
4646 if (out->pcm) {
4647 pcm_close(out->pcm);
4648 out->pcm = NULL;
4649 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004650 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4651 if (adev->haptic_pcm) {
4652 pcm_close(adev->haptic_pcm);
4653 adev->haptic_pcm = NULL;
4654 }
4655
4656 if (adev->haptic_buffer != NULL) {
4657 free(adev->haptic_buffer);
4658 adev->haptic_buffer = NULL;
4659 adev->haptic_buffer_size = 0;
4660 }
4661 adev->haptic_pcm_device_id = 0;
4662 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304663 } else {
4664 ALOGD("copl(%p):standby", out);
4665 out->send_next_track_params = false;
4666 out->is_compr_metadata_avail = false;
4667 out->gapless_mdata.encoder_delay = 0;
4668 out->gapless_mdata.encoder_padding = 0;
4669 if (out->compr != NULL) {
4670 compress_close(out->compr);
4671 out->compr = NULL;
4672 }
4673 }
4674 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004675 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304676 }
4677 ALOGD("%s: exit", __func__);
4678 return 0;
4679}
4680
Aalique Grahame22e49102018-12-18 14:23:57 -08004681static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682{
Aalique Grahame22e49102018-12-18 14:23:57 -08004683 struct stream_out *out = (struct stream_out *)stream;
4684
4685 // We try to get the lock for consistency,
4686 // but it isn't necessary for these variables.
4687 // If we're not in standby, we may be blocked on a write.
4688 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4689 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4690 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4691
Andy Hunga1f48fa2019-07-01 18:14:53 -07004692 char buffer[256]; // for statistics formatting
4693 if (!is_offload_usecase(out->usecase)) {
4694 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4695 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4696 }
4697
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004698 if (out->start_latency_ms.n > 0) {
4699 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4700 dprintf(fd, " Start latency ms: %s\n", buffer);
4701 }
4702
Aalique Grahame22e49102018-12-18 14:23:57 -08004703 if (locked) {
4704 pthread_mutex_unlock(&out->lock);
4705 }
4706
4707 // dump error info
4708 (void)error_log_dump(
4709 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 return 0;
4712}
4713
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004714static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4715{
4716 int ret = 0;
4717 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004718
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004719 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004720 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004721 return -EINVAL;
4722 }
4723
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304724 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004725
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004726 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4727 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304728 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004729 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004730 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4731 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304732 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004733 }
4734
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004735 ALOGV("%s new encoder delay %u and padding %u", __func__,
4736 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4737
4738 return 0;
4739}
4740
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004741static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4742{
4743 return out == adev->primary_output || out == adev->voice_tx_output;
4744}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004745
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304746// note: this call is safe only if the stream_cb is
4747// removed first in close_output_stream (as is done now).
4748static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4749{
4750 if (!stream || !parms)
4751 return;
4752
4753 struct stream_out *out = (struct stream_out *)stream;
4754 struct audio_device *adev = out->dev;
4755
4756 card_status_t status;
4757 int card;
4758 if (parse_snd_card_status(parms, &card, &status) < 0)
4759 return;
4760
4761 pthread_mutex_lock(&adev->lock);
4762 bool valid_cb = (card == adev->snd_card);
4763 pthread_mutex_unlock(&adev->lock);
4764
4765 if (!valid_cb)
4766 return;
4767
4768 lock_output_stream(out);
4769 if (out->card_status != status)
4770 out->card_status = status;
4771 pthread_mutex_unlock(&out->lock);
4772
4773 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4774 use_case_table[out->usecase],
4775 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4776
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304777 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304778 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304779 if (voice_is_call_state_active(adev) &&
4780 out == adev->primary_output) {
4781 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4782 pthread_mutex_lock(&adev->lock);
4783 voice_stop_call(adev);
4784 adev->mode = AUDIO_MODE_NORMAL;
4785 pthread_mutex_unlock(&adev->lock);
4786 }
4787 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304788 return;
4789}
4790
Kevin Rocardfce19002017-08-07 19:21:36 -07004791static int get_alive_usb_card(struct str_parms* parms) {
4792 int card;
4793 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4794 !audio_extn_usb_alive(card)) {
4795 return card;
4796 }
4797 return -ENODEV;
4798}
4799
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004800int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004801 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004802{
4803 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004804 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004805 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004806 bool bypass_a2dp = false;
4807 bool reconfig = false;
4808 unsigned long service_interval = 0;
4809
4810 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004811 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4812
4813 list_init(&new_devices);
4814 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004815
4816 lock_output_stream(out);
4817 pthread_mutex_lock(&adev->lock);
4818
4819 /*
4820 * When HDMI cable is unplugged the music playback is paused and
4821 * the policy manager sends routing=0. But the audioflinger continues
4822 * to write data until standby time (3sec). As the HDMI core is
4823 * turned off, the write gets blocked.
4824 * Avoid this by routing audio to speaker until standby.
4825 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004826 if (is_single_device_type_equal(&out->device_list,
4827 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004828 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004829 !audio_extn_passthru_is_passthrough_stream(out) &&
4830 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004831 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832 }
4833 /*
4834 * When A2DP is disconnected the
4835 * music playback is paused and the policy manager sends routing=0
4836 * But the audioflinger continues to write data until standby time
4837 * (3sec). As BT is turned off, the write gets blocked.
4838 * Avoid this by routing audio to speaker until standby.
4839 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004840 if (is_a2dp_out_device_type(&out->device_list) &&
4841 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004842 !audio_extn_a2dp_source_is_ready() &&
4843 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004844 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004845 }
4846 /*
4847 * When USB headset is disconnected the music platback paused
4848 * and the policy manager send routing=0. But if the USB is connected
4849 * back before the standby time, AFE is not closed and opened
4850 * when USB is connected back. So routing to speker will guarantee
4851 * AFE reconfiguration and AFE will be opend once USB is connected again
4852 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004853 if (is_usb_out_device_type(&out->device_list) &&
4854 list_empty(&new_devices) &&
4855 !audio_extn_usb_connected(NULL)) {
4856 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4857 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004858 /* To avoid a2dp to sco overlapping / BT device improper state
4859 * check with BT lib about a2dp streaming support before routing
4860 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004861 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004862 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004863 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4864 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004865 //combo usecase just by pass a2dp
4866 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4867 bypass_a2dp = true;
4868 } else {
4869 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4870 /* update device to a2dp and don't route as BT returned error
4871 * However it is still possible a2dp routing called because
4872 * of current active device disconnection (like wired headset)
4873 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004874 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004875 pthread_mutex_unlock(&adev->lock);
4876 pthread_mutex_unlock(&out->lock);
4877 goto error;
4878 }
4879 }
4880 }
4881
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004882 // Workaround: If routing to an non existing usb device, fail gracefully
4883 // The routing request will otherwise block during 10 second
4884 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004885 if (is_usb_out_device_type(&new_devices)) {
4886 struct str_parms *parms =
4887 str_parms_create_str(get_usb_device_address(&new_devices));
4888 if (!parms)
4889 goto error;
4890 if ((card = get_alive_usb_card(parms)) >= 0) {
4891 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4892 pthread_mutex_unlock(&adev->lock);
4893 pthread_mutex_unlock(&out->lock);
4894 str_parms_destroy(parms);
4895 ret = -ENOSYS;
4896 goto error;
4897 }
4898 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004899 }
4900
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004901 // Workaround: If routing to an non existing hdmi device, fail gracefully
4902 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4903 (platform_get_edid_info_v2(adev->platform,
4904 out->extconn.cs.controller,
4905 out->extconn.cs.stream) != 0)) {
4906 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4907 pthread_mutex_unlock(&adev->lock);
4908 pthread_mutex_unlock(&out->lock);
4909 ret = -ENOSYS;
4910 goto error;
4911 }
4912
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004913 /*
4914 * select_devices() call below switches all the usecases on the same
4915 * backend to the new device. Refer to check_usecases_codec_backend() in
4916 * the select_devices(). But how do we undo this?
4917 *
4918 * For example, music playback is active on headset (deep-buffer usecase)
4919 * and if we go to ringtones and select a ringtone, low-latency usecase
4920 * will be started on headset+speaker. As we can't enable headset+speaker
4921 * and headset devices at the same time, select_devices() switches the music
4922 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4923 * So when the ringtone playback is completed, how do we undo the same?
4924 *
4925 * We are relying on the out_set_parameters() call on deep-buffer output,
4926 * once the ringtone playback is ended.
4927 * NOTE: We should not check if the current devices are same as new devices.
4928 * Because select_devices() must be called to switch back the music
4929 * playback to headset.
4930 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004931 if (!list_empty(&new_devices)) {
4932 bool same_dev = compare_devices(&out->device_list, &new_devices);
4933 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004934
4935 if (output_drives_call(adev, out)) {
4936 if (!voice_is_call_state_active(adev)) {
4937 if (adev->mode == AUDIO_MODE_IN_CALL) {
4938 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004939 ret = voice_start_call(adev);
4940 }
4941 } else {
4942 adev->current_call_output = out;
4943 voice_update_devices_for_all_voice_usecases(adev);
4944 }
4945 }
4946
Mingshu Pang60536d72020-09-09 15:28:22 +08004947 if (is_usb_out_device_type(&out->device_list)) {
4948 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4949 audio_extn_usb_set_service_interval(true /*playback*/,
4950 service_interval,
4951 &reconfig);
4952 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4953 }
4954
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004955 if (!out->standby) {
4956 if (!same_dev) {
4957 ALOGV("update routing change");
4958 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4959 adev->perf_lock_opts,
4960 adev->perf_lock_opts_size);
4961 if (adev->adm_on_routing_change)
4962 adev->adm_on_routing_change(adev->adm_data,
4963 out->handle);
4964 }
4965 if (!bypass_a2dp) {
4966 select_devices(adev, out->usecase);
4967 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004968 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4969 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004970 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004971 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004972 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004973 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004974 }
4975
4976 if (!same_dev) {
4977 // on device switch force swap, lower functions will make sure
4978 // to check if swap is allowed or not.
4979 platform_set_swap_channels(adev, true);
4980 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4981 }
4982 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004983 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004984 pthread_mutex_lock(&out->latch_lock);
4985 if (out->a2dp_compress_mute) {
4986 out->a2dp_compress_mute = false;
4987 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4988 }
4989 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4991 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4992 }
4993 }
4994 }
4995
4996 pthread_mutex_unlock(&adev->lock);
4997 pthread_mutex_unlock(&out->lock);
4998
4999 /*handles device and call state changes*/
5000 audio_extn_extspk_update(adev->extspk);
5001
5002error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005003 ALOGV("%s: exit: code(%d)", __func__, ret);
5004 return ret;
5005}
5006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5008{
5009 struct stream_out *out = (struct stream_out *)stream;
5010 struct audio_device *adev = out->dev;
5011 struct str_parms *parms;
5012 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005013 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005014 int ext_controller = -1;
5015 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016
sangwoobc677242013-08-08 16:53:43 +09005017 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005018 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305020 if (!parms)
5021 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005022
5023 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5024 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005025 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005026 out->extconn.cs.controller = ext_controller;
5027 out->extconn.cs.stream = ext_stream;
5028 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5029 use_case_table[out->usecase], out->extconn.cs.controller,
5030 out->extconn.cs.stream);
5031 }
5032
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005033 if (out == adev->primary_output) {
5034 pthread_mutex_lock(&adev->lock);
5035 audio_extn_set_parameters(adev, parms);
5036 pthread_mutex_unlock(&adev->lock);
5037 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005038 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005039 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005040 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005041
5042 audio_extn_dts_create_state_notifier_node(out->usecase);
5043 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5044 popcount(out->channel_mask),
5045 out->playback_started);
5046
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005047 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005048 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005049
Surendar Karkaf51b5842018-04-26 11:28:38 +05305050 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5051 sizeof(value));
5052 if (err >= 0) {
5053 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5054 audio_extn_send_dual_mono_mixing_coefficients(out);
5055 }
5056
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305057 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5058 if (err >= 0) {
5059 strlcpy(out->profile, value, sizeof(out->profile));
5060 ALOGV("updating stream profile with value '%s'", out->profile);
5061 lock_output_stream(out);
5062 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5063 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005064 &out->device_list, out->flags,
5065 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305066 out->sample_rate, out->bit_width,
5067 out->channel_mask, out->profile,
5068 &out->app_type_cfg);
5069 pthread_mutex_unlock(&out->lock);
5070 }
5071
Alexy Joseph98988832017-01-13 14:56:59 -08005072 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005073 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5074 // and vendor.audio.hal.output.suspend.supported is set to true
5075 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005076 //check suspend parameter only for low latency and if the property
5077 //is enabled
5078 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5079 ALOGI("%s: got suspend_playback %s", __func__, value);
5080 lock_output_stream(out);
5081 if (!strncmp(value, "false", 5)) {
5082 //suspend_playback=false is supposed to set QOS value back to 75%
5083 //the mixer control sent with value Enable will achieve that
5084 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5085 } else if (!strncmp (value, "true", 4)) {
5086 //suspend_playback=true is supposed to remove QOS value
5087 //resetting the mixer control will set the default value
5088 //for the mixer control which is Disable and this removes the QOS vote
5089 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5090 } else {
5091 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5092 " got %s", __func__, value);
5093 ret = -1;
5094 }
5095
5096 if (ret != 0) {
5097 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5098 __func__, out->pm_qos_mixer_path, ret);
5099 }
5100
5101 pthread_mutex_unlock(&out->lock);
5102 }
5103 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005104
Alexy Joseph98988832017-01-13 14:56:59 -08005105 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005106 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305107error:
Eric Laurent994a6932013-07-17 11:51:42 -07005108 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005109 return ret;
5110}
5111
Paul McLeana50b7332018-12-17 08:24:21 -07005112static int in_set_microphone_direction(const struct audio_stream_in *stream,
5113 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005114 struct stream_in *in = (struct stream_in *)stream;
5115
5116 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5117
5118 in->direction = dir;
5119
5120 if (in->standby)
5121 return 0;
5122
5123 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005124}
5125
5126static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005127 struct stream_in *in = (struct stream_in *)stream;
5128
5129 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5130
5131 if (zoom > 1.0 || zoom < -1.0)
5132 return -EINVAL;
5133
5134 in->zoom = zoom;
5135
5136 if (in->standby)
5137 return 0;
5138
5139 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005140}
5141
5142
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005143static bool stream_get_parameter_channels(struct str_parms *query,
5144 struct str_parms *reply,
5145 audio_channel_mask_t *supported_channel_masks) {
5146 int ret = -1;
5147 char value[512];
5148 bool first = true;
5149 size_t i, j;
5150
5151 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5152 ret = 0;
5153 value[0] = '\0';
5154 i = 0;
5155 while (supported_channel_masks[i] != 0) {
5156 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5157 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5158 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305159 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005160
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305161 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005162 first = false;
5163 break;
5164 }
5165 }
5166 i++;
5167 }
5168 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5169 }
5170 return ret == 0;
5171}
5172
5173static bool stream_get_parameter_formats(struct str_parms *query,
5174 struct str_parms *reply,
5175 audio_format_t *supported_formats) {
5176 int ret = -1;
5177 char value[256];
5178 size_t i, j;
5179 bool first = true;
5180
5181 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5182 ret = 0;
5183 value[0] = '\0';
5184 i = 0;
5185 while (supported_formats[i] != 0) {
5186 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5187 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5188 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305189 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005190 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305191 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005192 first = false;
5193 break;
5194 }
5195 }
5196 i++;
5197 }
5198 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5199 }
5200 return ret == 0;
5201}
5202
5203static bool stream_get_parameter_rates(struct str_parms *query,
5204 struct str_parms *reply,
5205 uint32_t *supported_sample_rates) {
5206
5207 int i;
5208 char value[256];
5209 int ret = -1;
5210 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5211 ret = 0;
5212 value[0] = '\0';
5213 i=0;
5214 int cursor = 0;
5215 while (supported_sample_rates[i]) {
5216 int avail = sizeof(value) - cursor;
5217 ret = snprintf(value + cursor, avail, "%s%d",
5218 cursor > 0 ? "|" : "",
5219 supported_sample_rates[i]);
5220 if (ret < 0 || ret >= avail) {
5221 // if cursor is at the last element of the array
5222 // overwrite with \0 is duplicate work as
5223 // snprintf already put a \0 in place.
5224 // else
5225 // we had space to write the '|' at value[cursor]
5226 // (which will be overwritten) or no space to fill
5227 // the first element (=> cursor == 0)
5228 value[cursor] = '\0';
5229 break;
5230 }
5231 cursor += ret;
5232 ++i;
5233 }
5234 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5235 value);
5236 }
5237 return ret >= 0;
5238}
5239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5241{
5242 struct stream_out *out = (struct stream_out *)stream;
5243 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005244 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 char value[256];
5246 struct str_parms *reply = str_parms_create();
5247 size_t i, j;
5248 int ret;
5249 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005250
5251 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005252 if (reply) {
5253 str_parms_destroy(reply);
5254 }
5255 if (query) {
5256 str_parms_destroy(query);
5257 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005258 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5259 return NULL;
5260 }
5261
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005262 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5264 if (ret >= 0) {
5265 value[0] = '\0';
5266 i = 0;
5267 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005268 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5269 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005271 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005273 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005274 first = false;
5275 break;
5276 }
5277 }
5278 i++;
5279 }
5280 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5281 str = str_parms_to_str(reply);
5282 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005283 voice_extn_out_get_parameters(out, query, reply);
5284 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005285 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005286
Alexy Joseph62142aa2015-11-16 15:10:34 -08005287
5288 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5289 if (ret >= 0) {
5290 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305291 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5292 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005293 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305294 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005295 } else {
5296 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305297 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005298 }
5299 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005300 if (str)
5301 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005302 str = str_parms_to_str(reply);
5303 }
5304
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005305 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5306 if (ret >= 0) {
5307 value[0] = '\0';
5308 i = 0;
5309 first = true;
5310 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005311 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5312 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005313 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005314 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005315 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005316 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005317 first = false;
5318 break;
5319 }
5320 }
5321 i++;
5322 }
5323 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005324 if (str)
5325 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005326 str = str_parms_to_str(reply);
5327 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005328
5329 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5330 if (ret >= 0) {
5331 value[0] = '\0';
5332 i = 0;
5333 first = true;
5334 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005335 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5336 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005337 if (!first) {
5338 strlcat(value, "|", sizeof(value));
5339 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005340 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005341 first = false;
5342 break;
5343 }
5344 }
5345 i++;
5346 }
5347 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5348 if (str)
5349 free(str);
5350 str = str_parms_to_str(reply);
5351 }
5352
Alexy Joseph98988832017-01-13 14:56:59 -08005353 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5354 //only low latency track supports suspend_resume
5355 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005356 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005357 if (str)
5358 free(str);
5359 str = str_parms_to_str(reply);
5360 }
5361
5362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363 str_parms_destroy(query);
5364 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005365 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005366 return str;
5367}
5368
5369static uint32_t out_get_latency(const struct audio_stream_out *stream)
5370{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005371 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005372 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005373 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374
Alexy Josephaa54c872014-12-03 02:46:47 -08005375 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305376 lock_output_stream(out);
5377 latency = audio_extn_utils_compress_get_dsp_latency(out);
5378 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005379 } else if ((out->realtime) ||
5380 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005381 // since the buffer won't be filled up faster than realtime,
5382 // return a smaller number
5383 if (out->config.rate)
5384 period_ms = (out->af_period_multiplier * out->config.period_size *
5385 1000) / (out->config.rate);
5386 else
5387 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005388 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005389 } else {
5390 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005391 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005392 }
5393
Zhou Songd2537a02020-06-11 22:04:46 +08005394 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005395 latency += audio_extn_a2dp_get_encoder_latency();
5396
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305397 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005398 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005399}
5400
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305401static float AmpToDb(float amplification)
5402{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305403 float db = DSD_VOLUME_MIN_DB;
5404 if (amplification > 0) {
5405 db = 20 * log10(amplification);
5406 if(db < DSD_VOLUME_MIN_DB)
5407 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305408 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305409 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305410}
5411
Arun Mirpuri5d170872019-03-26 13:21:31 -07005412static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5413 float right)
5414{
5415 struct stream_out *out = (struct stream_out *)stream;
5416 long volume = 0;
5417 char mixer_ctl_name[128] = "";
5418 struct audio_device *adev = out->dev;
5419 struct mixer_ctl *ctl = NULL;
5420 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5421 PCM_PLAYBACK);
5422
5423 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5424 "Playback %d Volume", pcm_device_id);
5425 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5426 if (!ctl) {
5427 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5428 __func__, mixer_ctl_name);
5429 return -EINVAL;
5430 }
5431 if (left != right)
5432 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5433 __func__, left, right);
5434 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5435 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5436 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5437 __func__, mixer_ctl_name, volume);
5438 return -EINVAL;
5439 }
5440 return 0;
5441}
5442
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305443static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5444 float right)
5445{
5446 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305447 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305448 char mixer_ctl_name[128];
5449 struct audio_device *adev = out->dev;
5450 struct mixer_ctl *ctl;
5451 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5452 PCM_PLAYBACK);
5453
5454 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5455 "Compress Playback %d Volume", pcm_device_id);
5456 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5457 if (!ctl) {
5458 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5459 __func__, mixer_ctl_name);
5460 return -EINVAL;
5461 }
5462 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5463 __func__, mixer_ctl_name, left, right);
5464 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5465 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5466 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5467
5468 return 0;
5469}
5470
Zhou Song2b8f28f2017-09-11 10:51:38 +08005471static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5472 float right)
5473{
5474 struct stream_out *out = (struct stream_out *)stream;
5475 char mixer_ctl_name[] = "App Type Gain";
5476 struct audio_device *adev = out->dev;
5477 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305478 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005479
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005480 if (!is_valid_volume(left, right)) {
5481 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5482 __func__, left, right);
5483 return -EINVAL;
5484 }
5485
Zhou Song2b8f28f2017-09-11 10:51:38 +08005486 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5487 if (!ctl) {
5488 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5489 __func__, mixer_ctl_name);
5490 return -EINVAL;
5491 }
5492
5493 set_values[0] = 0; //0: Rx Session 1:Tx Session
5494 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305495 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5496 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005497
5498 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5499 return 0;
5500}
5501
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305502static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5503 float right)
5504{
5505 struct stream_out *out = (struct stream_out *)stream;
5506 /* Volume control for pcm playback */
5507 if (left != right) {
5508 return -EINVAL;
5509 } else {
5510 char mixer_ctl_name[128];
5511 struct audio_device *adev = out->dev;
5512 struct mixer_ctl *ctl;
5513 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5514 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5515 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5516 if (!ctl) {
5517 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5518 return -EINVAL;
5519 }
5520
5521 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5522 int ret = mixer_ctl_set_value(ctl, 0, volume);
5523 if (ret < 0) {
5524 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5525 return -EINVAL;
5526 }
5527
5528 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5529
5530 return 0;
5531 }
5532}
5533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005534static int out_set_volume(struct audio_stream_out *stream, float left,
5535 float right)
5536{
Eric Laurenta9024de2013-04-04 09:19:12 -07005537 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005538 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305539 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005540
Arun Mirpuri5d170872019-03-26 13:21:31 -07005541 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005542 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5543 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005544 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005545 out->muted = (left == 0.0f);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005546 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005547 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005548 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305549 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005550 /*
5551 * Set mute or umute on HDMI passthrough stream.
5552 * Only take left channel into account.
5553 * Mute is 0 and unmute 1
5554 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305555 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305556 } else if (out->format == AUDIO_FORMAT_DSD){
5557 char mixer_ctl_name[128] = "DSD Volume";
5558 struct audio_device *adev = out->dev;
5559 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5560
5561 if (!ctl) {
5562 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5563 __func__, mixer_ctl_name);
5564 return -EINVAL;
5565 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305566 volume[0] = (long)(AmpToDb(left));
5567 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305568 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5569 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005570 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005571 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005572 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5573 struct listnode *node = NULL;
5574 list_for_each(node, &adev->active_outputs_list) {
5575 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5576 streams_output_ctxt_t,
5577 list);
5578 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5579 out->volume_l = out_ctxt->output->volume_l;
5580 out->volume_r = out_ctxt->output->volume_r;
5581 }
5582 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005583 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005584 if (!out->a2dp_compress_mute) {
5585 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5586 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005587 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005588 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005589 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005590 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005591 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305592 if (!out->a2dp_compress_mute)
5593 ret = out_set_compr_volume(stream, left, right);
5594 out->volume_l = left;
5595 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005596 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305597 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005598 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005599 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005600 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5601 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5602 if (!out->standby) {
5603 audio_extn_utils_send_app_type_gain(out->dev,
5604 out->app_type_cfg.app_type,
5605 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005606 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005607 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005608 out->volume_l = left;
5609 out->volume_r = right;
5610 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005611 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5612 ALOGV("%s: MMAP set volume called", __func__);
5613 if (!out->standby)
5614 ret = out_set_mmap_volume(stream, left, right);
5615 out->volume_l = left;
5616 out->volume_r = right;
5617 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305618 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305619 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5620 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305621 /* Volume control for pcm playback */
5622 if (!out->standby)
5623 ret = out_set_pcm_volume(stream, left, right);
5624 else
5625 out->apply_volume = true;
5626
5627 out->volume_l = left;
5628 out->volume_r = right;
5629 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005630 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5631 ALOGV("%s: bus device set volume called", __func__);
5632 if (!out->standby)
5633 ret = out_set_pcm_volume(stream, left, right);
5634 out->volume_l = left;
5635 out->volume_r = right;
5636 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005637 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005639 return -ENOSYS;
5640}
5641
Zhou Songc9672822017-08-16 16:01:39 +08005642static void update_frames_written(struct stream_out *out, size_t bytes)
5643{
5644 size_t bpf = 0;
5645
5646 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5647 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5648 bpf = 1;
5649 else if (!is_offload_usecase(out->usecase))
5650 bpf = audio_bytes_per_sample(out->format) *
5651 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005652
5653 pthread_mutex_lock(&out->position_query_lock);
5654 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005655 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005656 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5657 }
5658 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005659}
5660
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005661int split_and_write_audio_haptic_data(struct stream_out *out,
5662 const void *buffer, size_t bytes_to_write)
5663{
5664 struct audio_device *adev = out->dev;
5665
5666 int ret = 0;
5667 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5668 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5669 size_t frame_size = channel_count * bytes_per_sample;
5670 size_t frame_count = bytes_to_write / frame_size;
5671
5672 bool force_haptic_path =
5673 property_get_bool("vendor.audio.test_haptic", false);
5674
5675 // extract Haptics data from Audio buffer
5676 bool alloc_haptic_buffer = false;
5677 int haptic_channel_count = adev->haptics_config.channels;
5678 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5679 size_t audio_frame_size = frame_size - haptic_frame_size;
5680 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5681
5682 if (adev->haptic_buffer == NULL) {
5683 alloc_haptic_buffer = true;
5684 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5685 free(adev->haptic_buffer);
5686 adev->haptic_buffer_size = 0;
5687 alloc_haptic_buffer = true;
5688 }
5689
5690 if (alloc_haptic_buffer) {
5691 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005692 if(adev->haptic_buffer == NULL) {
5693 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5694 return -ENOMEM;
5695 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005696 adev->haptic_buffer_size = total_haptic_buffer_size;
5697 }
5698
5699 size_t src_index = 0, aud_index = 0, hap_index = 0;
5700 uint8_t *audio_buffer = (uint8_t *)buffer;
5701 uint8_t *haptic_buffer = adev->haptic_buffer;
5702
5703 // This is required for testing only. This works for stereo data only.
5704 // One channel is fed to audio stream and other to haptic stream for testing.
5705 if (force_haptic_path)
5706 audio_frame_size = haptic_frame_size = bytes_per_sample;
5707
5708 for (size_t i = 0; i < frame_count; i++) {
5709 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5710 audio_frame_size);
5711 aud_index += audio_frame_size;
5712 src_index += audio_frame_size;
5713
5714 if (adev->haptic_pcm)
5715 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5716 haptic_frame_size);
5717 hap_index += haptic_frame_size;
5718 src_index += haptic_frame_size;
5719
5720 // This is required for testing only.
5721 // Discard haptic channel data.
5722 if (force_haptic_path)
5723 src_index += haptic_frame_size;
5724 }
5725
5726 // write to audio pipeline
5727 ret = pcm_write(out->pcm, (void *)audio_buffer,
5728 frame_count * audio_frame_size);
5729
5730 // write to haptics pipeline
5731 if (adev->haptic_pcm)
5732 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5733 frame_count * haptic_frame_size);
5734
5735 return ret;
5736}
5737
Aalique Grahame22e49102018-12-18 14:23:57 -08005738#ifdef NO_AUDIO_OUT
5739static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5740 const void *buffer __unused, size_t bytes)
5741{
5742 struct stream_out *out = (struct stream_out *)stream;
5743
5744 /* No Output device supported other than BT for playback.
5745 * Sleep for the amount of buffer duration
5746 */
5747 lock_output_stream(out);
5748 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5749 (const struct audio_stream_out *)&out->stream) /
5750 out_get_sample_rate(&out->stream.common));
5751 pthread_mutex_unlock(&out->lock);
5752 return bytes;
5753}
5754#endif
5755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005756static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5757 size_t bytes)
5758{
5759 struct stream_out *out = (struct stream_out *)stream;
5760 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005761 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305762 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005763 const size_t frame_size = audio_stream_out_frame_size(stream);
5764 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305765 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005766 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005767
Haynes Mathew George380745d2017-10-04 15:27:45 -07005768 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005769 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305770
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305771 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005772
Dhananjay Kumarac341582017-02-23 23:42:25 +05305773 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305774 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305775 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5776 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005777 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305778 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305779 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305780 ALOGD(" %s: sound card is not active/SSR state", __func__);
5781 ret= -EIO;
5782 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305783 }
5784 }
5785
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305786 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305787 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305788 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305789 goto exit;
5790 }
5791
Haynes Mathew George16081042017-05-31 17:16:49 -07005792 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5793 ret = -EINVAL;
5794 goto exit;
5795 }
5796
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005797 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305798 !out->is_iec61937_info_available) {
5799
5800 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5801 out->is_iec61937_info_available = true;
5802 } else if (audio_extn_passthru_is_enabled()) {
5803 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305804 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305805
5806 if((out->format == AUDIO_FORMAT_DTS) ||
5807 (out->format == AUDIO_FORMAT_DTS_HD)) {
5808 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5809 buffer, bytes);
5810 if (ret) {
5811 if (ret != -ENOSYS) {
5812 out->is_iec61937_info_available = false;
5813 ALOGD("iec61937 transmission info not yet updated retry");
5814 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305815 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305816 /* if stream has started and after that there is
5817 * stream config change (iec transmission config)
5818 * then trigger select_device to update backend configuration.
5819 */
5820 out->stream_config_changed = true;
5821 pthread_mutex_lock(&adev->lock);
5822 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305823 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005824 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305825 ret = -EINVAL;
5826 goto exit;
5827 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305828 pthread_mutex_unlock(&adev->lock);
5829 out->stream_config_changed = false;
5830 out->is_iec61937_info_available = true;
5831 }
5832 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305833
Meng Wang4c32fb42020-01-16 17:57:11 +08005834#ifdef AUDIO_GKI_ENABLED
5835 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5836 compr_passthr = out->compr_config.codec->reserved[0];
5837#else
5838 compr_passthr = out->compr_config.codec->compr_passthr;
5839#endif
5840
Garmond Leung317cbf12017-09-13 16:20:50 -07005841 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005842 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305843 (out->is_iec61937_info_available == true)) {
5844 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5845 ret = -EINVAL;
5846 goto exit;
5847 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305848 }
5849 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305850
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005851 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005852 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005853 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5854 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305855 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305856 ret = -EIO;
5857 goto exit;
5858 }
5859 }
5860 }
5861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005862 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005863 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005864 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5865
Eric Laurent150dbfe2013-02-27 14:31:02 -08005866 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005867 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5868 ret = voice_extn_compress_voip_start_output_stream(out);
5869 else
5870 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005871 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005872 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005873 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005874 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005875 goto exit;
5876 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305877 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005878 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005879
5880 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005881 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005882 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305883 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005884 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005885 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305886
5887 if ((out->is_iec61937_info_available == true) &&
5888 (audio_extn_passthru_is_passthrough_stream(out))&&
5889 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5890 ret = -EINVAL;
5891 goto exit;
5892 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305893 if (out->set_dual_mono)
5894 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005895
5896 // log startup time in ms.
5897 simple_stats_log(
5898 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005899 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005901 if (adev->is_channel_status_set == false &&
5902 compare_device_type(&out->device_list,
5903 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005904 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305905 adev->is_channel_status_set = true;
5906 }
5907
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305908 if ((adev->use_old_pspd_mix_ctrl == true) &&
5909 (out->pspd_coeff_sent == false)) {
5910 /*
5911 * Need to resend pspd coefficients after stream started for
5912 * older kernel version as it does not save the coefficients
5913 * and also stream has to be started for coeff to apply.
5914 */
5915 usecase = get_usecase_from_list(adev, out->usecase);
5916 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305917 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305918 out->pspd_coeff_sent = true;
5919 }
5920 }
5921
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005922 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005923 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005924 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005925 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005926 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5927 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305928 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5929 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005930 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305931 out->send_next_track_params = false;
5932 out->is_compr_metadata_avail = false;
5933 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005934 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305935 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305936 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005937
Ashish Jain83a6cc22016-06-28 14:34:17 +05305938 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305939 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305940 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305941 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005942 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305943 return -EINVAL;
5944 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305945 audio_format_t dst_format = out->hal_op_format;
5946 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305947
Dieter Luecking5d57def2018-09-07 14:23:37 +02005948 /* prevent division-by-zero */
5949 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5950 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5951 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5952 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305953 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005954 ATRACE_END();
5955 return -EINVAL;
5956 }
5957
Ashish Jainf1eaa582016-05-23 20:54:24 +05305958 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5959 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5960
Ashish Jain83a6cc22016-06-28 14:34:17 +05305961 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305962 dst_format,
5963 buffer,
5964 src_format,
5965 frames);
5966
Ashish Jain83a6cc22016-06-28 14:34:17 +05305967 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305968 bytes_to_write);
5969
5970 /*Convert written bytes in audio flinger format*/
5971 if (ret > 0)
5972 ret = ((ret * format_to_bitwidth_table[out->format]) /
5973 format_to_bitwidth_table[dst_format]);
5974 }
5975 } else
5976 ret = compress_write(out->compr, buffer, bytes);
5977
Zhou Songc9672822017-08-16 16:01:39 +08005978 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5979 update_frames_written(out, bytes);
5980
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305981 if (ret < 0)
5982 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005983 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305984 /*msg to cb thread only if non blocking write is enabled*/
5985 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305986 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005987 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305988 } else if (-ENETRESET == ret) {
5989 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305990 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305991 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305992 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005993 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305994 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005995 }
Ashish Jain5106d362016-05-11 19:23:33 +05305996
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305997 /* Call compr start only when non-zero bytes of data is there to be rendered */
5998 if (!out->playback_started && ret > 0) {
5999 int status = compress_start(out->compr);
6000 if (status < 0) {
6001 ret = status;
6002 ALOGE("%s: compr start failed with err %d", __func__, errno);
6003 goto exit;
6004 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006005 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006006 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006007 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006009 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006010
6011 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6012 popcount(out->channel_mask),
6013 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006014 }
6015 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006016 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006017 return ret;
6018 } else {
6019 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006020 size_t bytes_to_write = bytes;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006021 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006022 if (out->muted)
6023 memset((void *)buffer, 0, bytes);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006024 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006025 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6026 __func__, frames, frame_size, bytes_to_write);
6027
Aalique Grahame22e49102018-12-18 14:23:57 -08006028 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006029 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6030 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6031 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006032 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6033 int16_t *src = (int16_t *)buffer;
6034 int16_t *dst = (int16_t *)buffer;
6035
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006036 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006037 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006038 "out_write called for %s use case with wrong properties",
6039 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006040
6041 /*
6042 * FIXME: this can be removed once audio flinger mixer supports
6043 * mono output
6044 */
6045
6046 /*
6047 * Code below goes over each frame in the buffer and adds both
6048 * L and R samples and then divides by 2 to convert to mono
6049 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006050 if (channel_count == 2) {
6051 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6052 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6053 }
6054 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006055 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006056 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006057
6058 // Note: since out_get_presentation_position() is called alternating with out_write()
6059 // by AudioFlinger, we can check underruns using the prior timestamp read.
6060 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6061 if (out->last_fifo_valid) {
6062 // compute drain to see if there is an underrun.
6063 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306064 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6065 int64_t frames_by_time =
6066 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6067 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006068 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6069
6070 if (underrun > 0) {
6071 simple_stats_log(&out->fifo_underruns, underrun);
6072
6073 ALOGW("%s: underrun(%lld) "
6074 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6075 __func__,
6076 (long long)out->fifo_underruns.n,
6077 (long long)frames_by_time,
6078 (long long)out->last_fifo_frames_remaining);
6079 }
6080 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6081 }
6082
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306083 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006084
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006085 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006086
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006087 if (out->config.rate)
6088 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6089 out->config.rate;
6090
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006091 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006092 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6093
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006094 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006095 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006096 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306097 out->convert_buffer != NULL) {
6098
6099 memcpy_by_audio_format(out->convert_buffer,
6100 out->hal_op_format,
6101 buffer,
6102 out->hal_ip_format,
6103 out->config.period_size * out->config.channels);
6104
6105 ret = pcm_write(out->pcm, out->convert_buffer,
6106 (out->config.period_size *
6107 out->config.channels *
6108 format_to_bitwidth_table[out->hal_op_format]));
6109 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306110 /*
6111 * To avoid underrun in DSP when the application is not pumping
6112 * data at required rate, check for the no. of bytes and ignore
6113 * pcm_write if it is less than actual buffer size.
6114 * It is a work around to a change in compress VOIP driver.
6115 */
6116 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6117 bytes < (out->config.period_size * out->config.channels *
6118 audio_bytes_per_sample(out->format))) {
6119 size_t voip_buf_size =
6120 out->config.period_size * out->config.channels *
6121 audio_bytes_per_sample(out->format);
6122 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6123 __func__, bytes, voip_buf_size);
6124 usleep(((uint64_t)voip_buf_size - bytes) *
6125 1000000 / audio_stream_out_frame_size(stream) /
6126 out_get_sample_rate(&out->stream.common));
6127 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006128 } else {
6129 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6130 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6131 else
6132 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6133 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306134 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006135
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006136 release_out_focus(out);
6137
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306138 if (ret < 0)
6139 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006140 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306141 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006143 }
6144
6145exit:
Zhou Songc9672822017-08-16 16:01:39 +08006146 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306147 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306148 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150 pthread_mutex_unlock(&out->lock);
6151
6152 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006153 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006154 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306155 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306156 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306157 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306158 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306159 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306160 out->standby = true;
6161 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306162 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006163 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6164 /* prevent division-by-zero */
6165 uint32_t stream_size = audio_stream_out_frame_size(stream);
6166 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006167
Dieter Luecking5d57def2018-09-07 14:23:37 +02006168 if ((stream_size == 0) || (srate == 0)) {
6169 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6170 ATRACE_END();
6171 return -EINVAL;
6172 }
6173 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6174 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006175 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306176 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006177 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006178 return ret;
6179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006180 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006181 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006182 return bytes;
6183}
6184
6185static int out_get_render_position(const struct audio_stream_out *stream,
6186 uint32_t *dsp_frames)
6187{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006188 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006189
6190 if (dsp_frames == NULL)
6191 return -EINVAL;
6192
6193 *dsp_frames = 0;
6194 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006195 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306196
6197 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6198 * this operation and adev_close_output_stream(where out gets reset).
6199 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306200 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006201 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306202 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006203 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306204 return 0;
6205 }
6206
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006207 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306208 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306209 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006210 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306211 if (ret < 0)
6212 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006213 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306214 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006215 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306216 if (-ENETRESET == ret) {
6217 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306218 out->card_status = CARD_STATUS_OFFLINE;
6219 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306220 } else if(ret < 0) {
6221 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306222 ret = -EINVAL;
6223 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306224 /*
6225 * Handle corner case where compress session is closed during SSR
6226 * and timestamp is queried
6227 */
6228 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306229 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306230 } else if (out->prev_card_status_offline) {
6231 ALOGE("ERROR: previously sound card was offline,return error");
6232 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306233 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306234 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006235 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306236 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306237 pthread_mutex_unlock(&out->lock);
6238 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006239 } else if (audio_is_linear_pcm(out->format)) {
6240 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006241 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006242 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006243 } else
6244 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006245}
6246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006247static int out_add_audio_effect(const struct audio_stream *stream __unused,
6248 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006249{
6250 return 0;
6251}
6252
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006253static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6254 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255{
6256 return 0;
6257}
6258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006259static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6260 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306262 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263}
6264
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006265static int out_get_presentation_position(const struct audio_stream_out *stream,
6266 uint64_t *frames, struct timespec *timestamp)
6267{
6268 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306269 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006270 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006271
Ashish Jain5106d362016-05-11 19:23:33 +05306272 /* below piece of code is not guarded against any lock because audioFliner serializes
6273 * this operation and adev_close_output_stream( where out gets reset).
6274 */
6275 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306276 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006277 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306278 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6279 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6280 return 0;
6281 }
6282
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006283 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006284
Ashish Jain5106d362016-05-11 19:23:33 +05306285 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6286 ret = compress_get_tstamp(out->compr, &dsp_frames,
6287 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006288 // Adjustment accounts for A2dp encoder latency with offload usecases
6289 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006290 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006291 unsigned long offset =
6292 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6293 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6294 }
Ashish Jain5106d362016-05-11 19:23:33 +05306295 ALOGVV("%s rendered frames %ld sample_rate %d",
6296 __func__, dsp_frames, out->sample_rate);
6297 *frames = dsp_frames;
6298 if (ret < 0)
6299 ret = -errno;
6300 if (-ENETRESET == ret) {
6301 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306302 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306303 ret = -EINVAL;
6304 } else
6305 ret = 0;
6306 /* this is the best we can do */
6307 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006308 } else {
6309 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006310 unsigned int avail;
6311 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006312 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006313 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006314
Andy Hunga1f48fa2019-07-01 18:14:53 -07006315 if (out->kernel_buffer_size > avail) {
6316 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6317 } else {
6318 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6319 __func__, avail, out->kernel_buffer_size);
6320 avail = out->kernel_buffer_size;
6321 frames_temp = out->last_fifo_frames_remaining = 0;
6322 }
6323 out->last_fifo_valid = true;
6324 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6325
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006326 if (out->written >= frames_temp)
6327 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006328
Andy Hunga1f48fa2019-07-01 18:14:53 -07006329 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6330 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6331
Weiyin Jiangd4633762018-03-16 12:05:03 +08006332 // This adjustment accounts for buffering after app processor.
6333 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006334 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006335 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006336 if (signed_frames >= frames_temp)
6337 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006338
Weiyin Jiangd4633762018-03-16 12:05:03 +08006339 // Adjustment accounts for A2dp encoder latency with non offload usecases
6340 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006341 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006342 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6343 if (signed_frames >= frames_temp)
6344 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006345 }
6346
6347 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006348 *frames = signed_frames;
6349 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006350 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006351 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6352 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006353 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306354 *frames = out->written;
6355 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306356 if (is_offload_usecase(out->usecase))
6357 ret = -EINVAL;
6358 else
6359 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006360 }
6361 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006362 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006363 return ret;
6364}
6365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006366static int out_set_callback(struct audio_stream_out *stream,
6367 stream_callback_t callback, void *cookie)
6368{
6369 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006370 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006371
6372 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006373 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006374 out->client_callback = callback;
6375 out->client_cookie = cookie;
6376 if (out->adsp_hdlr_stream_handle) {
6377 ret = audio_extn_adsp_hdlr_stream_set_callback(
6378 out->adsp_hdlr_stream_handle,
6379 callback,
6380 cookie);
6381 if (ret)
6382 ALOGW("%s:adsp hdlr callback registration failed %d",
6383 __func__, ret);
6384 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006385 pthread_mutex_unlock(&out->lock);
6386 return 0;
6387}
6388
6389static int out_pause(struct audio_stream_out* stream)
6390{
6391 struct stream_out *out = (struct stream_out *)stream;
6392 int status = -ENOSYS;
6393 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006394 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006395 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306396 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006397 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006398 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006399 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306400 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306401 status = compress_pause(out->compr);
6402
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006404
Mingming Yin21854652016-04-13 11:54:02 -07006405 if (audio_extn_passthru_is_active()) {
6406 ALOGV("offload use case, pause passthru");
6407 audio_extn_passthru_on_pause(out);
6408 }
6409
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306410 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006411 audio_extn_dts_notify_playback_state(out->usecase, 0,
6412 out->sample_rate, popcount(out->channel_mask),
6413 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006414 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006415 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006416 pthread_mutex_unlock(&out->lock);
6417 }
6418 return status;
6419}
6420
6421static int out_resume(struct audio_stream_out* stream)
6422{
6423 struct stream_out *out = (struct stream_out *)stream;
6424 int status = -ENOSYS;
6425 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006426 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006427 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306428 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006429 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006430 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006431 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306432 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306433 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006434 }
6435 if (!status) {
6436 out->offload_state = OFFLOAD_STATE_PLAYING;
6437 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306438 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006439 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6440 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006441 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006442 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006443 pthread_mutex_unlock(&out->lock);
6444 }
6445 return status;
6446}
6447
6448static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6449{
6450 struct stream_out *out = (struct stream_out *)stream;
6451 int status = -ENOSYS;
6452 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006453 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6456 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6457 else
6458 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6459 pthread_mutex_unlock(&out->lock);
6460 }
6461 return status;
6462}
6463
6464static int out_flush(struct audio_stream_out* stream)
6465{
6466 struct stream_out *out = (struct stream_out *)stream;
6467 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006468 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006469 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006470 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006471 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006472 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6473 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006474 } else {
6475 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6476 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006477 out->written = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006478 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006479 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006480 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006481 return 0;
6482 }
6483 return -ENOSYS;
6484}
6485
Haynes Mathew George16081042017-05-31 17:16:49 -07006486static int out_stop(const struct audio_stream_out* stream)
6487{
6488 struct stream_out *out = (struct stream_out *)stream;
6489 struct audio_device *adev = out->dev;
6490 int ret = -ENOSYS;
6491
6492 ALOGV("%s", __func__);
6493 pthread_mutex_lock(&adev->lock);
6494 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6495 out->playback_started && out->pcm != NULL) {
6496 pcm_stop(out->pcm);
6497 ret = stop_output_stream(out);
6498 out->playback_started = false;
6499 }
6500 pthread_mutex_unlock(&adev->lock);
6501 return ret;
6502}
6503
6504static int out_start(const struct audio_stream_out* stream)
6505{
6506 struct stream_out *out = (struct stream_out *)stream;
6507 struct audio_device *adev = out->dev;
6508 int ret = -ENOSYS;
6509
6510 ALOGV("%s", __func__);
6511 pthread_mutex_lock(&adev->lock);
6512 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6513 !out->playback_started && out->pcm != NULL) {
6514 ret = start_output_stream(out);
6515 if (ret == 0) {
6516 out->playback_started = true;
6517 }
6518 }
6519 pthread_mutex_unlock(&adev->lock);
6520 return ret;
6521}
6522
6523/*
6524 * Modify config->period_count based on min_size_frames
6525 */
6526static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6527{
6528 int periodCountRequested = (min_size_frames + config->period_size - 1)
6529 / config->period_size;
6530 int periodCount = MMAP_PERIOD_COUNT_MIN;
6531
6532 ALOGV("%s original config.period_size = %d config.period_count = %d",
6533 __func__, config->period_size, config->period_count);
6534
6535 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6536 periodCount *= 2;
6537 }
6538 config->period_count = periodCount;
6539
6540 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6541}
6542
Phil Burkfe17efd2019-03-25 10:23:35 -07006543// Read offset for the positional timestamp from a persistent vendor property.
6544// This is to workaround apparent inaccuracies in the timing information that
6545// is used by the AAudio timing model. The inaccuracies can cause glitches.
6546static int64_t get_mmap_out_time_offset() {
6547 const int32_t kDefaultOffsetMicros = 0;
6548 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006549 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006550 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6551 return mmap_time_offset_micros * (int64_t)1000;
6552}
6553
Haynes Mathew George16081042017-05-31 17:16:49 -07006554static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6555 int32_t min_size_frames,
6556 struct audio_mmap_buffer_info *info)
6557{
6558 struct stream_out *out = (struct stream_out *)stream;
6559 struct audio_device *adev = out->dev;
6560 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006561 unsigned int offset1 = 0;
6562 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006563 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006564 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006565 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006566
Arun Mirpuri5d170872019-03-26 13:21:31 -07006567 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306568 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006569 pthread_mutex_lock(&adev->lock);
6570
Sharad Sanglec6f32552018-05-04 16:15:38 +05306571 if (CARD_STATUS_OFFLINE == out->card_status ||
6572 CARD_STATUS_OFFLINE == adev->card_status) {
6573 ALOGW("out->card_status or adev->card_status offline, try again");
6574 ret = -EIO;
6575 goto exit;
6576 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306577 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006578 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6579 ret = -EINVAL;
6580 goto exit;
6581 }
6582 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6583 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6584 ret = -ENOSYS;
6585 goto exit;
6586 }
6587 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6588 if (out->pcm_device_id < 0) {
6589 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6590 __func__, out->pcm_device_id, out->usecase);
6591 ret = -EINVAL;
6592 goto exit;
6593 }
6594
6595 adjust_mmap_period_count(&out->config, min_size_frames);
6596
Arun Mirpuri5d170872019-03-26 13:21:31 -07006597 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006598 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6599 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6600 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306601 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306602 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6603 out->card_status = CARD_STATUS_OFFLINE;
6604 adev->card_status = CARD_STATUS_OFFLINE;
6605 ret = -EIO;
6606 goto exit;
6607 }
6608
Haynes Mathew George16081042017-05-31 17:16:49 -07006609 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6610 step = "open";
6611 ret = -ENODEV;
6612 goto exit;
6613 }
6614 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6615 if (ret < 0) {
6616 step = "begin";
6617 goto exit;
6618 }
juyuchen626833d2019-06-04 16:48:02 +08006619
6620 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006621 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006622 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006623 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006624 ret = platform_get_mmap_data_fd(adev->platform,
6625 out->pcm_device_id, 0 /*playback*/,
6626 &info->shared_memory_fd,
6627 &mmap_size);
6628 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006629 // Fall back to non exclusive mode
6630 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6631 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006632 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6633 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6634
Arun Mirpuri5d170872019-03-26 13:21:31 -07006635 if (mmap_size < buffer_size) {
6636 step = "mmap";
6637 goto exit;
6638 }
juyuchen626833d2019-06-04 16:48:02 +08006639 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006640 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006641 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006642 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006643
6644 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6645 if (ret < 0) {
6646 step = "commit";
6647 goto exit;
6648 }
6649
Phil Burkfe17efd2019-03-25 10:23:35 -07006650 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6651
Haynes Mathew George16081042017-05-31 17:16:49 -07006652 out->standby = false;
6653 ret = 0;
6654
Arun Mirpuri5d170872019-03-26 13:21:31 -07006655 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006656 __func__, info->shared_memory_address, info->buffer_size_frames);
6657
6658exit:
6659 if (ret != 0) {
6660 if (out->pcm == NULL) {
6661 ALOGE("%s: %s - %d", __func__, step, ret);
6662 } else {
6663 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6664 pcm_close(out->pcm);
6665 out->pcm = NULL;
6666 }
6667 }
6668 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306669 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006670 return ret;
6671}
6672
6673static int out_get_mmap_position(const struct audio_stream_out *stream,
6674 struct audio_mmap_position *position)
6675{
6676 struct stream_out *out = (struct stream_out *)stream;
6677 ALOGVV("%s", __func__);
6678 if (position == NULL) {
6679 return -EINVAL;
6680 }
6681 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006682 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006683 return -ENOSYS;
6684 }
6685 if (out->pcm == NULL) {
6686 return -ENOSYS;
6687 }
6688
6689 struct timespec ts = { 0, 0 };
6690 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6691 if (ret < 0) {
6692 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6693 return ret;
6694 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006695 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6696 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006697 return 0;
6698}
6699
6700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701/** audio_stream_in implementation **/
6702static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6703{
6704 struct stream_in *in = (struct stream_in *)stream;
6705
6706 return in->config.rate;
6707}
6708
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006709static int in_set_sample_rate(struct audio_stream *stream __unused,
6710 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711{
6712 return -ENOSYS;
6713}
6714
6715static size_t in_get_buffer_size(const struct audio_stream *stream)
6716{
6717 struct stream_in *in = (struct stream_in *)stream;
6718
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006719 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6720 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006721 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6722 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306723 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306724 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006725
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006726 return in->config.period_size * in->af_period_multiplier *
6727 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006728}
6729
6730static uint32_t in_get_channels(const struct audio_stream *stream)
6731{
6732 struct stream_in *in = (struct stream_in *)stream;
6733
6734 return in->channel_mask;
6735}
6736
6737static audio_format_t in_get_format(const struct audio_stream *stream)
6738{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006739 struct stream_in *in = (struct stream_in *)stream;
6740
6741 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006742}
6743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006744static int in_set_format(struct audio_stream *stream __unused,
6745 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006746{
6747 return -ENOSYS;
6748}
6749
6750static int in_standby(struct audio_stream *stream)
6751{
6752 struct stream_in *in = (struct stream_in *)stream;
6753 struct audio_device *adev = in->dev;
6754 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306755 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6756 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006757 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306758
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006759 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006760 if (!in->standby && in->is_st_session) {
6761 ALOGD("%s: sound trigger pcm stop lab", __func__);
6762 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006763 if (adev->num_va_sessions > 0)
6764 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006765 in->standby = 1;
6766 }
6767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006768 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006769 if (adev->adm_deregister_stream)
6770 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6771
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006773 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006774 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006775 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006776 voice_extn_compress_voip_close_input_stream(stream);
6777 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006778 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6779 do_stop = in->capture_started;
6780 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006781 if (in->mmap_shared_memory_fd >= 0) {
6782 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6783 __func__, in->mmap_shared_memory_fd);
6784 close(in->mmap_shared_memory_fd);
6785 in->mmap_shared_memory_fd = -1;
6786 }
Zhou Songa8895042016-07-05 17:54:22 +08006787 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306788 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306789 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006790 }
6791
Arun Mirpuri5d170872019-03-26 13:21:31 -07006792 if (in->pcm) {
6793 ATRACE_BEGIN("pcm_in_close");
6794 pcm_close(in->pcm);
6795 ATRACE_END();
6796 in->pcm = NULL;
6797 }
6798
Carter Hsu2e429db2019-05-14 18:50:52 +08006799 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006800 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006801
George Gao3018ede2019-10-23 13:23:00 -07006802 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6803 if (adev->num_va_sessions > 0)
6804 adev->num_va_sessions--;
6805 }
Quinn Malef6050362019-01-30 15:55:40 -08006806
Eric Laurent150dbfe2013-02-27 14:31:02 -08006807 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006808 }
6809 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006810 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006811 return status;
6812}
6813
Aalique Grahame22e49102018-12-18 14:23:57 -08006814static int in_dump(const struct audio_stream *stream,
6815 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006816{
Aalique Grahame22e49102018-12-18 14:23:57 -08006817 struct stream_in *in = (struct stream_in *)stream;
6818
6819 // We try to get the lock for consistency,
6820 // but it isn't necessary for these variables.
6821 // If we're not in standby, we may be blocked on a read.
6822 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6823 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6824 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6825 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6826
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006827 char buffer[256]; // for statistics formatting
6828 if (in->start_latency_ms.n > 0) {
6829 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6830 dprintf(fd, " Start latency ms: %s\n", buffer);
6831 }
6832
Aalique Grahame22e49102018-12-18 14:23:57 -08006833 if (locked) {
6834 pthread_mutex_unlock(&in->lock);
6835 }
6836
6837 // dump error info
6838 (void)error_log_dump(
6839 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006841 return 0;
6842}
6843
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306844static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6845{
6846 if (!stream || !parms)
6847 return;
6848
6849 struct stream_in *in = (struct stream_in *)stream;
6850 struct audio_device *adev = in->dev;
6851
6852 card_status_t status;
6853 int card;
6854 if (parse_snd_card_status(parms, &card, &status) < 0)
6855 return;
6856
6857 pthread_mutex_lock(&adev->lock);
6858 bool valid_cb = (card == adev->snd_card);
6859 pthread_mutex_unlock(&adev->lock);
6860
6861 if (!valid_cb)
6862 return;
6863
6864 lock_input_stream(in);
6865 if (in->card_status != status)
6866 in->card_status = status;
6867 pthread_mutex_unlock(&in->lock);
6868
6869 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6870 use_case_table[in->usecase],
6871 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6872
6873 // a better solution would be to report error back to AF and let
6874 // it put the stream to standby
6875 if (status == CARD_STATUS_OFFLINE)
6876 in_standby(&in->stream.common);
6877
6878 return;
6879}
6880
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006881int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006882 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006883 audio_source_t source)
6884{
6885 struct audio_device *adev = in->dev;
6886 int ret = 0;
6887
6888 lock_input_stream(in);
6889 pthread_mutex_lock(&adev->lock);
6890
6891 /* no audio source uses val == 0 */
6892 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6893 in->source = source;
6894 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6895 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6896 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6897 (in->config.rate == 8000 || in->config.rate == 16000 ||
6898 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6899 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6900 ret = voice_extn_compress_voip_open_input_stream(in);
6901 if (ret != 0) {
6902 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6903 __func__, ret);
6904 }
6905 }
6906 }
6907
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006908 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6909 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006910 // Workaround: If routing to an non existing usb device, fail gracefully
6911 // The routing request will otherwise block during 10 second
6912 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006913 struct str_parms *usb_addr =
6914 str_parms_create_str(get_usb_device_address(devices));
6915 if (is_usb_in_device_type(devices) && usb_addr &&
6916 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006917 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6918 ret = -ENOSYS;
6919 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006920 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006921 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006922 if (!in->standby && !in->is_st_session) {
6923 ALOGV("update input routing change");
6924 // inform adm before actual routing to prevent glitches.
6925 if (adev->adm_on_routing_change) {
6926 adev->adm_on_routing_change(adev->adm_data,
6927 in->capture_handle);
6928 ret = select_devices(adev, in->usecase);
6929 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6930 adev->adm_routing_changed = true;
6931 }
6932 }
6933 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006934 if (usb_addr)
6935 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006936 }
6937 pthread_mutex_unlock(&adev->lock);
6938 pthread_mutex_unlock(&in->lock);
6939
6940 ALOGD("%s: exit: status(%d)", __func__, ret);
6941 return ret;
6942}
6943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006944static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6945{
6946 struct stream_in *in = (struct stream_in *)stream;
6947 struct audio_device *adev = in->dev;
6948 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006949 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306950 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306952 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006953 parms = str_parms_create_str(kvpairs);
6954
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306955 if (!parms)
6956 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006957 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006958 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006959
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306960 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6961 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306962 strlcpy(in->profile, value, sizeof(in->profile));
6963 ALOGV("updating stream profile with value '%s'", in->profile);
6964 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6965 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006966 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306967 in->sample_rate, in->bit_width,
6968 in->profile, &in->app_type_cfg);
6969 }
6970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006971 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006972 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973
6974 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306975error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306976 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006977}
6978
6979static char* in_get_parameters(const struct audio_stream *stream,
6980 const char *keys)
6981{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006982 struct stream_in *in = (struct stream_in *)stream;
6983 struct str_parms *query = str_parms_create_str(keys);
6984 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006985 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006986
6987 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006988 if (reply) {
6989 str_parms_destroy(reply);
6990 }
6991 if (query) {
6992 str_parms_destroy(query);
6993 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006994 ALOGE("in_get_parameters: failed to create query or reply");
6995 return NULL;
6996 }
6997
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006998 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006999
7000 voice_extn_in_get_parameters(in, query, reply);
7001
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007002 stream_get_parameter_channels(query, reply,
7003 &in->supported_channel_masks[0]);
7004 stream_get_parameter_formats(query, reply,
7005 &in->supported_formats[0]);
7006 stream_get_parameter_rates(query, reply,
7007 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007008 str = str_parms_to_str(reply);
7009 str_parms_destroy(query);
7010 str_parms_destroy(reply);
7011
7012 ALOGV("%s: exit: returns - %s", __func__, str);
7013 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007014}
7015
Aalique Grahame22e49102018-12-18 14:23:57 -08007016static int in_set_gain(struct audio_stream_in *stream,
7017 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007018{
Aalique Grahame22e49102018-12-18 14:23:57 -08007019 struct stream_in *in = (struct stream_in *)stream;
7020 char mixer_ctl_name[128];
7021 struct mixer_ctl *ctl;
7022 int ctl_value;
7023
7024 ALOGV("%s: gain %f", __func__, gain);
7025
7026 if (stream == NULL)
7027 return -EINVAL;
7028
7029 /* in_set_gain() only used to silence MMAP capture for now */
7030 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7031 return -ENOSYS;
7032
7033 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7034
7035 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7036 if (!ctl) {
7037 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7038 __func__, mixer_ctl_name);
7039 return -ENOSYS;
7040 }
7041
7042 if (gain < RECORD_GAIN_MIN)
7043 gain = RECORD_GAIN_MIN;
7044 else if (gain > RECORD_GAIN_MAX)
7045 gain = RECORD_GAIN_MAX;
7046 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7047
7048 mixer_ctl_set_value(ctl, 0, ctl_value);
7049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050 return 0;
7051}
7052
7053static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7054 size_t bytes)
7055{
7056 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307057
7058 if (in == NULL) {
7059 ALOGE("%s: stream_in ptr is NULL", __func__);
7060 return -EINVAL;
7061 }
7062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007063 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307064 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307065 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007066
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007067 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307068
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007069 if (in->is_st_session) {
7070 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7071 /* Read from sound trigger HAL */
7072 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007073 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007074 if (adev->num_va_sessions < UINT_MAX)
7075 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007076 in->standby = 0;
7077 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007078 pthread_mutex_unlock(&in->lock);
7079 return bytes;
7080 }
7081
Haynes Mathew George16081042017-05-31 17:16:49 -07007082 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7083 ret = -ENOSYS;
7084 goto exit;
7085 }
7086
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007087 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7088 !in->standby && adev->adm_routing_changed) {
7089 ret = -ENOSYS;
7090 goto exit;
7091 }
7092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007093 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007094 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7095
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007096 pthread_mutex_lock(&adev->lock);
7097 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7098 ret = voice_extn_compress_voip_start_input_stream(in);
7099 else
7100 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007101 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7102 if (adev->num_va_sessions < UINT_MAX)
7103 adev->num_va_sessions++;
7104 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007105 pthread_mutex_unlock(&adev->lock);
7106 if (ret != 0) {
7107 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007108 }
7109 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007110
7111 // log startup time in ms.
7112 simple_stats_log(
7113 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307116 /* Avoid read if capture_stopped is set */
7117 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7118 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7119 ret = -EINVAL;
7120 goto exit;
7121 }
7122
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007123 // what's the duration requested by the client?
7124 long ns = 0;
7125
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307126 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007127 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7128 in->config.rate;
7129
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007130 ret = request_in_focus(in, ns);
7131 if (ret != 0)
7132 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007133 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007134
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307135 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307136 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7137 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307138 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007139 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307140 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007141 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007142 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007143 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007144 } else if (audio_extn_ffv_get_stream() == in) {
7145 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307146 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007147 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307148 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7149 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7150 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7151 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307152 ret = -EINVAL;
7153 goto exit;
7154 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307155 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307156 ret = -errno;
7157 }
7158 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307159 /* bytes read is always set to bytes for non compress usecases */
7160 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161 }
7162
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007163 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007165 /*
Quinn Malef6050362019-01-30 15:55:40 -08007166 * Instead of writing zeroes here, we could trust the hardware to always
7167 * provide zeroes when muted. This is also muted with voice recognition
7168 * usecases so that other clients do not have access to voice recognition
7169 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 */
Quinn Malef6050362019-01-30 15:55:40 -08007171 if ((ret == 0 && voice_get_mic_mute(adev) &&
7172 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007173 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7174 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007175 (adev->num_va_sessions &&
7176 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7177 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7178 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007179 memset(buffer, 0, bytes);
7180
7181exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307182 frame_size = audio_stream_in_frame_size(stream);
7183 if (frame_size > 0)
7184 in->frames_read += bytes_read/frame_size;
7185
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007186 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307187 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188 pthread_mutex_unlock(&in->lock);
7189
7190 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307191 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307192 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307193 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307194 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307195 in->standby = true;
7196 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307197 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307198 bytes_read = bytes;
7199 memset(buffer, 0, bytes);
7200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007202 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7203 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007204 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307205 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307206 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307208 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007209}
7210
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007211static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007212{
7213 return 0;
7214}
7215
Aalique Grahame22e49102018-12-18 14:23:57 -08007216static int in_get_capture_position(const struct audio_stream_in *stream,
7217 int64_t *frames, int64_t *time)
7218{
7219 if (stream == NULL || frames == NULL || time == NULL) {
7220 return -EINVAL;
7221 }
7222 struct stream_in *in = (struct stream_in *)stream;
7223 int ret = -ENOSYS;
7224
7225 lock_input_stream(in);
7226 // note: ST sessions do not close the alsa pcm driver synchronously
7227 // on standby. Therefore, we may return an error even though the
7228 // pcm stream is still opened.
7229 if (in->standby) {
7230 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7231 "%s stream in standby but pcm not NULL for non ST session", __func__);
7232 goto exit;
7233 }
7234 if (in->pcm) {
7235 struct timespec timestamp;
7236 unsigned int avail;
7237 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7238 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007239 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007240 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007241 ret = 0;
7242 }
7243 }
7244exit:
7245 pthread_mutex_unlock(&in->lock);
7246 return ret;
7247}
7248
Carter Hsu2e429db2019-05-14 18:50:52 +08007249static int in_update_effect_list(bool add, effect_handle_t effect,
7250 struct listnode *head)
7251{
7252 struct listnode *node;
7253 struct in_effect_list *elist = NULL;
7254 struct in_effect_list *target = NULL;
7255 int ret = 0;
7256
7257 if (!head)
7258 return ret;
7259
7260 list_for_each(node, head) {
7261 elist = node_to_item(node, struct in_effect_list, list);
7262 if (elist->handle == effect) {
7263 target = elist;
7264 break;
7265 }
7266 }
7267
7268 if (add) {
7269 if (target) {
7270 ALOGD("effect %p already exist", effect);
7271 return ret;
7272 }
7273
7274 target = (struct in_effect_list *)
7275 calloc(1, sizeof(struct in_effect_list));
7276
7277 if (!target) {
7278 ALOGE("%s:fail to allocate memory", __func__);
7279 return -ENOMEM;
7280 }
7281
7282 target->handle = effect;
7283 list_add_tail(head, &target->list);
7284 } else {
7285 if (target) {
7286 list_remove(&target->list);
7287 free(target);
7288 }
7289 }
7290
7291 return ret;
7292}
7293
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007294static int add_remove_audio_effect(const struct audio_stream *stream,
7295 effect_handle_t effect,
7296 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007297{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007298 struct stream_in *in = (struct stream_in *)stream;
7299 int status = 0;
7300 effect_descriptor_t desc;
7301
7302 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007303 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7304
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007305 if (status != 0)
7306 return status;
7307
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007308 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007309 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007310 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007311 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7312 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007313 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007314
7315 in_update_effect_list(enable, effect, &in->aec_list);
7316 enable = !list_empty(&in->aec_list);
7317 if (enable == in->enable_aec)
7318 goto exit;
7319
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007320 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007321 ALOGD("AEC enable %d", enable);
7322
Aalique Grahame22e49102018-12-18 14:23:57 -08007323 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7324 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7325 in->dev->enable_voicerx = enable;
7326 struct audio_usecase *usecase;
7327 struct listnode *node;
7328 list_for_each(node, &in->dev->usecase_list) {
7329 usecase = node_to_item(node, struct audio_usecase, list);
7330 if (usecase->type == PCM_PLAYBACK)
7331 select_devices(in->dev, usecase->id);
7332 }
7333 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007334 if (!in->standby) {
7335 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7336 select_devices(in->dev, in->usecase);
7337 }
7338
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007339 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007340 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7341
7342 in_update_effect_list(enable, effect, &in->ns_list);
7343 enable = !list_empty(&in->ns_list);
7344 if (enable == in->enable_ns)
7345 goto exit;
7346
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007347 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007348 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007349 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007350 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7351 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007352 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7353 select_devices(in->dev, in->usecase);
7354 } else
7355 select_devices(in->dev, in->usecase);
7356 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007357 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007358exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007359 pthread_mutex_unlock(&in->dev->lock);
7360 pthread_mutex_unlock(&in->lock);
7361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362 return 0;
7363}
7364
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007365static int in_add_audio_effect(const struct audio_stream *stream,
7366 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007367{
Eric Laurent994a6932013-07-17 11:51:42 -07007368 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007369 return add_remove_audio_effect(stream, effect, true);
7370}
7371
7372static int in_remove_audio_effect(const struct audio_stream *stream,
7373 effect_handle_t effect)
7374{
Eric Laurent994a6932013-07-17 11:51:42 -07007375 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007376 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007377}
7378
Derek Chenf939fb72018-11-13 13:34:41 -08007379streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7380 audio_io_handle_t input)
7381{
7382 struct listnode *node;
7383
7384 list_for_each(node, &dev->active_inputs_list) {
7385 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7386 streams_input_ctxt_t,
7387 list);
7388 if (in_ctxt->input->capture_handle == input) {
7389 return in_ctxt;
7390 }
7391 }
7392 return NULL;
7393}
7394
7395streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7396 audio_io_handle_t output)
7397{
7398 struct listnode *node;
7399
7400 list_for_each(node, &dev->active_outputs_list) {
7401 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7402 streams_output_ctxt_t,
7403 list);
7404 if (out_ctxt->output->handle == output) {
7405 return out_ctxt;
7406 }
7407 }
7408 return NULL;
7409}
7410
Haynes Mathew George16081042017-05-31 17:16:49 -07007411static int in_stop(const struct audio_stream_in* stream)
7412{
7413 struct stream_in *in = (struct stream_in *)stream;
7414 struct audio_device *adev = in->dev;
7415
7416 int ret = -ENOSYS;
7417 ALOGV("%s", __func__);
7418 pthread_mutex_lock(&adev->lock);
7419 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7420 in->capture_started && in->pcm != NULL) {
7421 pcm_stop(in->pcm);
7422 ret = stop_input_stream(in);
7423 in->capture_started = false;
7424 }
7425 pthread_mutex_unlock(&adev->lock);
7426 return ret;
7427}
7428
7429static int in_start(const struct audio_stream_in* stream)
7430{
7431 struct stream_in *in = (struct stream_in *)stream;
7432 struct audio_device *adev = in->dev;
7433 int ret = -ENOSYS;
7434
7435 ALOGV("%s in %p", __func__, in);
7436 pthread_mutex_lock(&adev->lock);
7437 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7438 !in->capture_started && in->pcm != NULL) {
7439 if (!in->capture_started) {
7440 ret = start_input_stream(in);
7441 if (ret == 0) {
7442 in->capture_started = true;
7443 }
7444 }
7445 }
7446 pthread_mutex_unlock(&adev->lock);
7447 return ret;
7448}
7449
Phil Burke0a86d12019-02-16 22:28:11 -08007450// Read offset for the positional timestamp from a persistent vendor property.
7451// This is to workaround apparent inaccuracies in the timing information that
7452// is used by the AAudio timing model. The inaccuracies can cause glitches.
7453static int64_t in_get_mmap_time_offset() {
7454 const int32_t kDefaultOffsetMicros = 0;
7455 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007456 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007457 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7458 return mmap_time_offset_micros * (int64_t)1000;
7459}
7460
Haynes Mathew George16081042017-05-31 17:16:49 -07007461static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7462 int32_t min_size_frames,
7463 struct audio_mmap_buffer_info *info)
7464{
7465 struct stream_in *in = (struct stream_in *)stream;
7466 struct audio_device *adev = in->dev;
7467 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007468 unsigned int offset1 = 0;
7469 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007470 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007471 uint32_t mmap_size = 0;
7472 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007473
7474 pthread_mutex_lock(&adev->lock);
7475 ALOGV("%s in %p", __func__, in);
7476
Sharad Sanglec6f32552018-05-04 16:15:38 +05307477 if (CARD_STATUS_OFFLINE == in->card_status||
7478 CARD_STATUS_OFFLINE == adev->card_status) {
7479 ALOGW("in->card_status or adev->card_status offline, try again");
7480 ret = -EIO;
7481 goto exit;
7482 }
7483
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307484 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007485 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7486 ret = -EINVAL;
7487 goto exit;
7488 }
7489 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7490 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7491 ALOGV("%s in %p", __func__, in);
7492 ret = -ENOSYS;
7493 goto exit;
7494 }
7495 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7496 if (in->pcm_device_id < 0) {
7497 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7498 __func__, in->pcm_device_id, in->usecase);
7499 ret = -EINVAL;
7500 goto exit;
7501 }
7502
7503 adjust_mmap_period_count(&in->config, min_size_frames);
7504
7505 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7506 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7507 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7508 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307509 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307510 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7511 in->card_status = CARD_STATUS_OFFLINE;
7512 adev->card_status = CARD_STATUS_OFFLINE;
7513 ret = -EIO;
7514 goto exit;
7515 }
7516
Haynes Mathew George16081042017-05-31 17:16:49 -07007517 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7518 step = "open";
7519 ret = -ENODEV;
7520 goto exit;
7521 }
7522
7523 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7524 if (ret < 0) {
7525 step = "begin";
7526 goto exit;
7527 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007528
juyuchen626833d2019-06-04 16:48:02 +08007529 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007530 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7531 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7532 info->burst_size_frames = in->config.period_size;
7533 ret = platform_get_mmap_data_fd(adev->platform,
7534 in->pcm_device_id, 1 /*capture*/,
7535 &info->shared_memory_fd,
7536 &mmap_size);
7537 if (ret < 0) {
7538 // Fall back to non exclusive mode
7539 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7540 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007541 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7542 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7543
Arun Mirpuri5d170872019-03-26 13:21:31 -07007544 if (mmap_size < buffer_size) {
7545 step = "mmap";
7546 goto exit;
7547 }
juyuchen626833d2019-06-04 16:48:02 +08007548 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007549 }
7550
7551 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007552
7553 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7554 if (ret < 0) {
7555 step = "commit";
7556 goto exit;
7557 }
7558
Phil Burke0a86d12019-02-16 22:28:11 -08007559 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7560
Haynes Mathew George16081042017-05-31 17:16:49 -07007561 in->standby = false;
7562 ret = 0;
7563
7564 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7565 __func__, info->shared_memory_address, info->buffer_size_frames);
7566
7567exit:
7568 if (ret != 0) {
7569 if (in->pcm == NULL) {
7570 ALOGE("%s: %s - %d", __func__, step, ret);
7571 } else {
7572 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7573 pcm_close(in->pcm);
7574 in->pcm = NULL;
7575 }
7576 }
7577 pthread_mutex_unlock(&adev->lock);
7578 return ret;
7579}
7580
7581static int in_get_mmap_position(const struct audio_stream_in *stream,
7582 struct audio_mmap_position *position)
7583{
7584 struct stream_in *in = (struct stream_in *)stream;
7585 ALOGVV("%s", __func__);
7586 if (position == NULL) {
7587 return -EINVAL;
7588 }
7589 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7590 return -ENOSYS;
7591 }
7592 if (in->pcm == NULL) {
7593 return -ENOSYS;
7594 }
7595 struct timespec ts = { 0, 0 };
7596 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7597 if (ret < 0) {
7598 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7599 return ret;
7600 }
Phil Burke0a86d12019-02-16 22:28:11 -08007601 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7602 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007603 return 0;
7604}
7605
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307606static int in_get_active_microphones(const struct audio_stream_in *stream,
7607 struct audio_microphone_characteristic_t *mic_array,
7608 size_t *mic_count) {
7609 struct stream_in *in = (struct stream_in *)stream;
7610 struct audio_device *adev = in->dev;
7611 ALOGVV("%s", __func__);
7612
7613 lock_input_stream(in);
7614 pthread_mutex_lock(&adev->lock);
7615 int ret = platform_get_active_microphones(adev->platform,
7616 audio_channel_count_from_in_mask(in->channel_mask),
7617 in->usecase, mic_array, mic_count);
7618 pthread_mutex_unlock(&adev->lock);
7619 pthread_mutex_unlock(&in->lock);
7620
7621 return ret;
7622}
7623
7624static int adev_get_microphones(const struct audio_hw_device *dev,
7625 struct audio_microphone_characteristic_t *mic_array,
7626 size_t *mic_count) {
7627 struct audio_device *adev = (struct audio_device *)dev;
7628 ALOGVV("%s", __func__);
7629
7630 pthread_mutex_lock(&adev->lock);
7631 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7632 pthread_mutex_unlock(&adev->lock);
7633
7634 return ret;
7635}
juyuchendb308c22019-01-21 11:57:17 -07007636
7637static void in_update_sink_metadata(struct audio_stream_in *stream,
7638 const struct sink_metadata *sink_metadata) {
7639
7640 if (stream == NULL
7641 || sink_metadata == NULL
7642 || sink_metadata->tracks == NULL) {
7643 return;
7644 }
7645
7646 int error = 0;
7647 struct stream_in *in = (struct stream_in *)stream;
7648 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007649 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007650 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007651
7652 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007653
7654 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007655 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007656
7657 lock_input_stream(in);
7658 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007659 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007660
Zhou Song62ea0282020-03-22 19:53:01 +08007661 is_ha_usecase = adev->ha_proxy_enable ?
7662 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7663 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7664 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007665 && adev->voice_tx_output != NULL) {
7666 /* Use the rx device from afe-proxy record to route voice call because
7667 there is no routing if tx device is on primary hal and rx device
7668 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007669 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007670
7671 if (!voice_is_call_state_active(adev)) {
7672 if (adev->mode == AUDIO_MODE_IN_CALL) {
7673 adev->current_call_output = adev->voice_tx_output;
7674 error = voice_start_call(adev);
7675 if (error != 0)
7676 ALOGE("%s: start voice call failed %d", __func__, error);
7677 }
7678 } else {
7679 adev->current_call_output = adev->voice_tx_output;
7680 voice_update_devices_for_all_voice_usecases(adev);
7681 }
7682 }
7683
7684 pthread_mutex_unlock(&adev->lock);
7685 pthread_mutex_unlock(&in->lock);
7686}
7687
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307688int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007689 audio_io_handle_t handle,
7690 audio_devices_t devices,
7691 audio_output_flags_t flags,
7692 struct audio_config *config,
7693 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007694 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007695{
7696 struct audio_device *adev = (struct audio_device *)dev;
7697 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307698 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007699 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007700 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307701 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007702 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7703 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7704 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7705 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007706 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007707 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7708 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007709 bool force_haptic_path =
7710 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007711 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007712#ifdef AUDIO_GKI_ENABLED
7713 __s32 *generic_dec;
7714#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007715
kunleizdff872d2018-08-20 14:40:33 +08007716 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007717 is_usb_dev = false;
7718 devices = AUDIO_DEVICE_OUT_SPEAKER;
7719 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7720 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007721 if (config->format == AUDIO_FORMAT_DEFAULT)
7722 config->format = AUDIO_FORMAT_PCM_16_BIT;
7723 if (config->sample_rate == 0)
7724 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7725 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7726 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007727 }
7728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007729 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307730
Rahul Sharma99770982019-03-06 17:05:26 +05307731 pthread_mutex_lock(&adev->lock);
7732 if (out_get_stream(adev, handle) != NULL) {
7733 ALOGW("%s, output stream already opened", __func__);
7734 ret = -EEXIST;
7735 }
7736 pthread_mutex_unlock(&adev->lock);
7737 if (ret)
7738 return ret;
7739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007740 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7741
Mingming Yin3a941d42016-02-17 18:08:05 -08007742 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007743 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7744 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307745
7746
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007747 if (!out) {
7748 return -ENOMEM;
7749 }
7750
Haynes Mathew George204045b2015-02-25 20:32:03 -08007751 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007752 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007753 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007754 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007755 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007757 if (devices == AUDIO_DEVICE_NONE)
7758 devices = AUDIO_DEVICE_OUT_SPEAKER;
7759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007760 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007761 list_init(&out->device_list);
7762 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007763 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007764 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007765 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307766 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307767 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7768 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7769 else
7770 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007771 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007772 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007773 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307774 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307775 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307776 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007777 out->hal_output_suspend_supported = 0;
7778 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307779 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307780 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307781 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007782 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007783
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307784 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307785 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007786 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7787
Aalique Grahame22e49102018-12-18 14:23:57 -08007788 if (direct_dev &&
7789 (audio_is_linear_pcm(out->format) ||
7790 config->format == AUDIO_FORMAT_DEFAULT) &&
7791 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7792 audio_format_t req_format = config->format;
7793 audio_channel_mask_t req_channel_mask = config->channel_mask;
7794 uint32_t req_sample_rate = config->sample_rate;
7795
7796 pthread_mutex_lock(&adev->lock);
7797 if (is_hdmi) {
7798 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7799 ret = read_hdmi_sink_caps(out);
7800 if (config->sample_rate == 0)
7801 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7802 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7803 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7804 if (config->format == AUDIO_FORMAT_DEFAULT)
7805 config->format = AUDIO_FORMAT_PCM_16_BIT;
7806 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007807 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7808 &config->format,
7809 &out->supported_formats[0],
7810 MAX_SUPPORTED_FORMATS,
7811 &config->channel_mask,
7812 &out->supported_channel_masks[0],
7813 MAX_SUPPORTED_CHANNEL_MASKS,
7814 &config->sample_rate,
7815 &out->supported_sample_rates[0],
7816 MAX_SUPPORTED_SAMPLE_RATES);
7817 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007818 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007819
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007820 pthread_mutex_unlock(&adev->lock);
7821 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007822 if (ret == -ENOSYS) {
7823 /* ignore and go with default */
7824 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007825 }
7826 // For MMAP NO IRQ, allow conversions in ADSP
7827 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7828 goto error_open;
7829 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007830 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007831 goto error_open;
7832 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007833
7834 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7835 config->sample_rate = req_sample_rate;
7836 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7837 config->channel_mask = req_channel_mask;
7838 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7839 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007840 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007841
7842 out->sample_rate = config->sample_rate;
7843 out->channel_mask = config->channel_mask;
7844 out->format = config->format;
7845 if (is_hdmi) {
7846 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7847 out->config = pcm_config_hdmi_multi;
7848 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7849 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7850 out->config = pcm_config_mmap_playback;
7851 out->stream.start = out_start;
7852 out->stream.stop = out_stop;
7853 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7854 out->stream.get_mmap_position = out_get_mmap_position;
7855 } else {
7856 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7857 out->config = pcm_config_hifi;
7858 }
7859
7860 out->config.rate = out->sample_rate;
7861 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7862 if (is_hdmi) {
7863 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7864 audio_bytes_per_sample(out->format));
7865 }
7866 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007867 }
7868
Derek Chenf6318be2017-06-12 17:16:24 -04007869 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007870 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007871 /* extract car audio stream index */
7872 out->car_audio_stream =
7873 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7874 if (out->car_audio_stream < 0) {
7875 ALOGE("%s: invalid car audio stream %x",
7876 __func__, out->car_audio_stream);
7877 ret = -EINVAL;
7878 goto error_open;
7879 }
Derek Chen5f67a942020-02-24 23:08:13 -08007880 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007881 }
7882
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007883 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007884 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007885 if (!voice_extn_is_compress_voip_supported()) {
7886 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7887 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007888 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307889 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007890 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7891 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007892 out->volume_l = INVALID_OUT_VOLUME;
7893 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007894
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007895 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007896 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007897 uint32_t channel_count =
7898 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307899 out->config.channels = channel_count;
7900
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007901 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7902 out->sample_rate, out->format,
7903 channel_count, false);
7904 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7905 if (frame_size != 0)
7906 out->config.period_size = buffer_size / frame_size;
7907 else
7908 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007909 }
7910 } else {
7911 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7912 voice_extn_compress_voip_is_active(out->dev)) &&
7913 (voice_extn_compress_voip_is_config_supported(config))) {
7914 ret = voice_extn_compress_voip_open_output_stream(out);
7915 if (ret != 0) {
7916 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7917 __func__, ret);
7918 goto error_open;
7919 }
Sujin Panicker19027262019-09-16 18:28:06 +05307920 } else {
7921 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7922 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007923 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007924 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007925 } else if (audio_is_linear_pcm(out->format) &&
7926 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7927 out->channel_mask = config->channel_mask;
7928 out->sample_rate = config->sample_rate;
7929 out->format = config->format;
7930 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7931 // does this change?
7932 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7933 out->config.rate = config->sample_rate;
7934 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7935 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7936 audio_bytes_per_sample(config->format));
7937 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007938 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307939 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307940 pthread_mutex_lock(&adev->lock);
7941 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7942 pthread_mutex_unlock(&adev->lock);
7943
7944 // reject offload during card offline to allow
7945 // fallback to s/w paths
7946 if (offline) {
7947 ret = -ENODEV;
7948 goto error_open;
7949 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007951 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7952 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7953 ALOGE("%s: Unsupported Offload information", __func__);
7954 ret = -EINVAL;
7955 goto error_open;
7956 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007957
Atul Khare3fa6e542017-08-09 00:56:17 +05307958 if (config->offload_info.format == 0)
7959 config->offload_info.format = config->format;
7960 if (config->offload_info.sample_rate == 0)
7961 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007962
Mingming Yin90310102013-11-13 16:57:00 -08007963 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307964 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007965 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007966 ret = -EINVAL;
7967 goto error_open;
7968 }
7969
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007970 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7971 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7972 (audio_extn_passthru_is_passthrough_stream(out)) &&
7973 !((config->sample_rate == 48000) ||
7974 (config->sample_rate == 96000) ||
7975 (config->sample_rate == 192000))) {
7976 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7977 __func__, config->sample_rate, config->offload_info.format);
7978 ret = -EINVAL;
7979 goto error_open;
7980 }
7981
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007982 out->compr_config.codec = (struct snd_codec *)
7983 calloc(1, sizeof(struct snd_codec));
7984
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007985 if (!out->compr_config.codec) {
7986 ret = -ENOMEM;
7987 goto error_open;
7988 }
7989
Dhananjay Kumarac341582017-02-23 23:42:25 +05307990 out->stream.pause = out_pause;
7991 out->stream.resume = out_resume;
7992 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307993 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307994 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007995 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307996 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007997 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307998 } else {
7999 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8000 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008001 }
vivek mehta446c3962015-09-14 10:57:35 -07008002
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308003 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8004 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008005#ifdef AUDIO_GKI_ENABLED
8006 /* out->compr_config.codec->reserved[1] is for flags */
8007 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8008#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308009 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008010#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308011 }
8012
vivek mehta446c3962015-09-14 10:57:35 -07008013 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008014 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008015 config->format == 0 && config->sample_rate == 0 &&
8016 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008017 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008018 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8019 } else {
8020 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8021 ret = -EEXIST;
8022 goto error_open;
8023 }
vivek mehta446c3962015-09-14 10:57:35 -07008024 }
8025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008026 if (config->offload_info.channel_mask)
8027 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008028 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008029 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008030 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008031 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308032 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008033 ret = -EINVAL;
8034 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008035 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008036
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008037 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008038 out->sample_rate = config->offload_info.sample_rate;
8039
Mingming Yin3ee55c62014-08-04 14:23:35 -07008040 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008041
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308042 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308043 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308044 audio_extn_dolby_send_ddp_endp_params(adev);
8045 audio_extn_dolby_set_dmid(adev);
8046 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008048 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008049 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 out->compr_config.codec->bit_rate =
8051 config->offload_info.bit_rate;
8052 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308053 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308055 /* Update bit width only for non passthrough usecases.
8056 * For passthrough usecases, the output will always be opened @16 bit
8057 */
8058 if (!audio_extn_passthru_is_passthrough_stream(out))
8059 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308060
8061 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008062#ifdef AUDIO_GKI_ENABLED
8063 /* out->compr_config.codec->reserved[1] is for flags */
8064 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8065 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8066#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308067 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8068 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008069#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308070
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008071 /*TODO: Do we need to change it for passthrough */
8072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008073
Manish Dewangana6fc5442015-08-24 20:30:31 +05308074 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8075 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308076 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308077 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308078 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8079 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308080
8081 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8082 AUDIO_FORMAT_PCM) {
8083
8084 /*Based on platform support, configure appropriate alsa format for corresponding
8085 *hal input format.
8086 */
8087 out->compr_config.codec->format = hal_format_to_alsa(
8088 config->offload_info.format);
8089
Ashish Jain83a6cc22016-06-28 14:34:17 +05308090 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308091 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308092 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308093
Dhananjay Kumarac341582017-02-23 23:42:25 +05308094 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308095 *hal input format and alsa format might differ based on platform support.
8096 */
8097 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308098 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308099
8100 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8101
Deeraj Soman93155a62019-09-30 19:00:37 +05308102 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8103 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8104 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8105 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8106 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308107
Ashish Jainf1eaa582016-05-23 20:54:24 +05308108 /* Check if alsa session is configured with the same format as HAL input format,
8109 * if not then derive correct fragment size needed to accomodate the
8110 * conversion of HAL input format to alsa format.
8111 */
8112 audio_extn_utils_update_direct_pcm_fragment_size(out);
8113
8114 /*if hal input and output fragment size is different this indicates HAL input format is
8115 *not same as the alsa format
8116 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308117 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308118 /*Allocate a buffer to convert input data to the alsa configured format.
8119 *size of convert buffer is equal to the size required to hold one fragment size
8120 *worth of pcm data, this is because flinger does not write more than fragment_size
8121 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308122 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8123 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308124 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8125 ret = -ENOMEM;
8126 goto error_open;
8127 }
8128 }
8129 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8130 out->compr_config.fragment_size =
8131 audio_extn_passthru_get_buffer_size(&config->offload_info);
8132 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8133 } else {
8134 out->compr_config.fragment_size =
8135 platform_get_compress_offload_buffer_size(&config->offload_info);
8136 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8137 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008138
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308139 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8140 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8141 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008142 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8143#ifdef AUDIO_GKI_ENABLED
8144 generic_dec =
8145 &(out->compr_config.codec->options.generic.reserved[1]);
8146 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8147 AUDIO_OUTPUT_BIT_WIDTH;
8148#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308149 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008150#endif
8151 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008152
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308153 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8154 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8155 }
8156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008157 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8158 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008159
Manish Dewangan69426c82017-01-30 17:35:36 +05308160 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8161 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8162 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8163 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8164 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8165 } else {
8166 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8167 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008168
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308169 memset(&out->channel_map_param, 0,
8170 sizeof(struct audio_out_channel_map_param));
8171
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008172 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308173 out->send_next_track_params = false;
8174 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008175 out->offload_state = OFFLOAD_STATE_IDLE;
8176 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008177 out->writeAt.tv_sec = 0;
8178 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008179
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008180 audio_extn_dts_create_state_notifier_node(out->usecase);
8181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008182 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8183 __func__, config->offload_info.version,
8184 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308185
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308186 /* Check if DSD audio format is supported in codec
8187 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308188 */
8189
8190 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308191 (!platform_check_codec_dsd_support(adev->platform) ||
8192 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308193 ret = -EINVAL;
8194 goto error_open;
8195 }
8196
Ashish Jain5106d362016-05-11 19:23:33 +05308197 /* Disable gapless if any of the following is true
8198 * passthrough playback
8199 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308200 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308201 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308202 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308203 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008204 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308205 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308206 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308207 check_and_set_gapless_mode(adev, false);
8208 } else
8209 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008210
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308211 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008212 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8213 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308214 if (config->format == AUDIO_FORMAT_DSD) {
8215 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008216#ifdef AUDIO_GKI_ENABLED
8217 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8218 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8219#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308220 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008221#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308222 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008223
8224 create_offload_callback_thread(out);
8225
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008226 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008227 switch (config->sample_rate) {
8228 case 0:
8229 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8230 break;
8231 case 8000:
8232 case 16000:
8233 case 48000:
8234 out->sample_rate = config->sample_rate;
8235 break;
8236 default:
8237 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8238 config->sample_rate);
8239 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8240 ret = -EINVAL;
8241 goto error_open;
8242 }
8243 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8244 switch (config->channel_mask) {
8245 case AUDIO_CHANNEL_NONE:
8246 case AUDIO_CHANNEL_OUT_STEREO:
8247 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8248 break;
8249 default:
8250 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8251 config->channel_mask);
8252 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8253 ret = -EINVAL;
8254 goto error_open;
8255 }
8256 switch (config->format) {
8257 case AUDIO_FORMAT_DEFAULT:
8258 case AUDIO_FORMAT_PCM_16_BIT:
8259 out->format = AUDIO_FORMAT_PCM_16_BIT;
8260 break;
8261 default:
8262 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8263 config->format);
8264 config->format = AUDIO_FORMAT_PCM_16_BIT;
8265 ret = -EINVAL;
8266 goto error_open;
8267 }
8268
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308269 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008270 if (ret != 0) {
8271 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008272 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008273 goto error_open;
8274 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008275 } else if (is_single_device_type_equal(&out->device_list,
8276 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008277 switch (config->sample_rate) {
8278 case 0:
8279 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8280 break;
8281 case 8000:
8282 case 16000:
8283 case 48000:
8284 out->sample_rate = config->sample_rate;
8285 break;
8286 default:
8287 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8288 config->sample_rate);
8289 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8290 ret = -EINVAL;
8291 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008292 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008293 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8294 switch (config->channel_mask) {
8295 case AUDIO_CHANNEL_NONE:
8296 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8297 break;
8298 case AUDIO_CHANNEL_OUT_STEREO:
8299 out->channel_mask = config->channel_mask;
8300 break;
8301 default:
8302 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8303 config->channel_mask);
8304 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8305 ret = -EINVAL;
8306 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008307 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008308 switch (config->format) {
8309 case AUDIO_FORMAT_DEFAULT:
8310 out->format = AUDIO_FORMAT_PCM_16_BIT;
8311 break;
8312 case AUDIO_FORMAT_PCM_16_BIT:
8313 out->format = config->format;
8314 break;
8315 default:
8316 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8317 config->format);
8318 config->format = AUDIO_FORMAT_PCM_16_BIT;
8319 ret = -EINVAL;
8320 break;
8321 }
8322 if (ret != 0)
8323 goto error_open;
8324
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008325 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8326 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008327 out->config.rate = out->sample_rate;
8328 out->config.channels =
8329 audio_channel_count_from_out_mask(out->channel_mask);
8330 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008331 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008332 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308333 unsigned int channels = 0;
8334 /*Update config params to default if not set by the caller*/
8335 if (config->sample_rate == 0)
8336 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8337 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8338 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8339 if (config->format == AUDIO_FORMAT_DEFAULT)
8340 config->format = AUDIO_FORMAT_PCM_16_BIT;
8341
8342 channels = audio_channel_count_from_out_mask(out->channel_mask);
8343
Varun Balaraje49253e2017-07-06 19:48:56 +05308344 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8345 out->usecase = get_interactive_usecase(adev);
8346 out->config = pcm_config_low_latency;
8347 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308348 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008349 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8350 out->flags);
8351 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008352 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8353 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8354 out->config = pcm_config_mmap_playback;
8355 out->stream.start = out_start;
8356 out->stream.stop = out_stop;
8357 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8358 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308359 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8360 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008361 out->hal_output_suspend_supported =
8362 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8363 out->dynamic_pm_qos_config_supported =
8364 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8365 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008366 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8367 } else {
8368 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8369 //the mixer path will be a string similar to "low-latency-playback resume"
8370 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8371 strlcat(out->pm_qos_mixer_path,
8372 " resume", MAX_MIXER_PATH_LEN);
8373 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8374 out->pm_qos_mixer_path);
8375 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308376 out->config = pcm_config_low_latency;
8377 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8378 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8379 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308380 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8381 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8382 if (out->config.period_size <= 0) {
8383 ALOGE("Invalid configuration period size is not valid");
8384 ret = -EINVAL;
8385 goto error_open;
8386 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008387 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8388 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8389 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008390 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8391 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8392 out->config = pcm_config_haptics_audio;
8393 if (force_haptic_path)
8394 adev->haptics_config = pcm_config_haptics_audio;
8395 else
8396 adev->haptics_config = pcm_config_haptics;
8397
Meng Wangd08ce322020-04-02 08:59:20 +08008398 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008399 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8400
8401 if (force_haptic_path) {
8402 out->config.channels = 1;
8403 adev->haptics_config.channels = 1;
8404 } else
8405 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 -08008406 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008407 ret = audio_extn_auto_hal_open_output_stream(out);
8408 if (ret) {
8409 ALOGE("%s: Failed to open output stream for bus device", __func__);
8410 ret = -EINVAL;
8411 goto error_open;
8412 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308413 } else {
8414 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008415 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8416 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308417 }
8418 out->hal_ip_format = format = out->format;
8419 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8420 out->hal_op_format = pcm_format_to_hal(out->config.format);
8421 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8422 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008423 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308424 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308425 if (out->hal_ip_format != out->hal_op_format) {
8426 uint32_t buffer_size = out->config.period_size *
8427 format_to_bitwidth_table[out->hal_op_format] *
8428 out->config.channels;
8429 out->convert_buffer = calloc(1, buffer_size);
8430 if (out->convert_buffer == NULL){
8431 ALOGE("Allocation failed for convert buffer for size %d",
8432 out->compr_config.fragment_size);
8433 ret = -ENOMEM;
8434 goto error_open;
8435 }
8436 ALOGD("Convert buffer allocated of size %d", buffer_size);
8437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008438 }
8439
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008440 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8441 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308442
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008443 /* TODO remove this hardcoding and check why width is zero*/
8444 if (out->bit_width == 0)
8445 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308446 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008447 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008448 &out->device_list, out->flags,
8449 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308450 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308451 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008452 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008453 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8454 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008455 if(adev->primary_output == NULL)
8456 adev->primary_output = out;
8457 else {
8458 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008459 ret = -EEXIST;
8460 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008461 }
8462 }
8463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464 /* Check if this usecase is already existing */
8465 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008466 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8467 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008468 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008469 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008470 ret = -EEXIST;
8471 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008472 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474 pthread_mutex_unlock(&adev->lock);
8475
8476 out->stream.common.get_sample_rate = out_get_sample_rate;
8477 out->stream.common.set_sample_rate = out_set_sample_rate;
8478 out->stream.common.get_buffer_size = out_get_buffer_size;
8479 out->stream.common.get_channels = out_get_channels;
8480 out->stream.common.get_format = out_get_format;
8481 out->stream.common.set_format = out_set_format;
8482 out->stream.common.standby = out_standby;
8483 out->stream.common.dump = out_dump;
8484 out->stream.common.set_parameters = out_set_parameters;
8485 out->stream.common.get_parameters = out_get_parameters;
8486 out->stream.common.add_audio_effect = out_add_audio_effect;
8487 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8488 out->stream.get_latency = out_get_latency;
8489 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008490#ifdef NO_AUDIO_OUT
8491 out->stream.write = out_write_for_no_output;
8492#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008494#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008495 out->stream.get_render_position = out_get_render_position;
8496 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008497 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498
Haynes Mathew George16081042017-05-31 17:16:49 -07008499 if (out->realtime)
8500 out->af_period_multiplier = af_period_multiplier;
8501 else
8502 out->af_period_multiplier = 1;
8503
Andy Hunga1f48fa2019-07-01 18:14:53 -07008504 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008507 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008508 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008509
8510 config->format = out->stream.common.get_format(&out->stream.common);
8511 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8512 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308513 register_format(out->format, out->supported_formats);
8514 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8515 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008516
Aalique Grahame22e49102018-12-18 14:23:57 -08008517 out->error_log = error_log_create(
8518 ERROR_LOG_ENTRIES,
8519 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8520
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308521 /*
8522 By locking output stream before registering, we allow the callback
8523 to update stream's state only after stream's initial state is set to
8524 adev state.
8525 */
8526 lock_output_stream(out);
8527 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8528 pthread_mutex_lock(&adev->lock);
8529 out->card_status = adev->card_status;
8530 pthread_mutex_unlock(&adev->lock);
8531 pthread_mutex_unlock(&out->lock);
8532
Aalique Grahame22e49102018-12-18 14:23:57 -08008533 stream_app_type_cfg_init(&out->app_type_cfg);
8534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008535 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308536 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008537 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008538
8539 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8540 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8541 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008542 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308543 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008544 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008545 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308546 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8547 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008548 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8549 out->usecase, PCM_PLAYBACK);
8550 hdlr_stream_cfg.flags = out->flags;
8551 hdlr_stream_cfg.type = PCM_PLAYBACK;
8552 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8553 &hdlr_stream_cfg);
8554 if (ret) {
8555 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8556 out->adsp_hdlr_stream_handle = NULL;
8557 }
8558 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308559 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8560 is_direct_passthough, false);
8561 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8562 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008563 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008564 if (ret < 0) {
8565 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8566 out->ip_hdlr_handle = NULL;
8567 }
8568 }
Derek Chenf939fb72018-11-13 13:34:41 -08008569
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008570 ret = io_streams_map_insert(adev, &out->stream.common,
8571 out->handle, AUDIO_PATCH_HANDLE_NONE);
8572 if (ret != 0)
8573 goto error_open;
8574
Derek Chenf939fb72018-11-13 13:34:41 -08008575 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8576 calloc(1, sizeof(streams_output_ctxt_t));
8577 if (out_ctxt == NULL) {
8578 ALOGE("%s fail to allocate output ctxt", __func__);
8579 ret = -ENOMEM;
8580 goto error_open;
8581 }
8582 out_ctxt->output = out;
8583
8584 pthread_mutex_lock(&adev->lock);
8585 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8586 pthread_mutex_unlock(&adev->lock);
8587
Eric Laurent994a6932013-07-17 11:51:42 -07008588 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008589 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008590
8591error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308592 if (out->convert_buffer)
8593 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008594 free(out);
8595 *stream_out = NULL;
8596 ALOGD("%s: exit: ret %d", __func__, ret);
8597 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008598}
8599
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308600void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008601 struct audio_stream_out *stream)
8602{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008603 struct stream_out *out = (struct stream_out *)stream;
8604 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008605 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008606
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008607 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308608
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008609 io_streams_map_remove(adev, out->handle);
8610
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308611 // must deregister from sndmonitor first to prevent races
8612 // between the callback and close_stream
8613 audio_extn_snd_mon_unregister_listener(out);
8614
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008615 /* close adsp hdrl session before standby */
8616 if (out->adsp_hdlr_stream_handle) {
8617 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8618 if (ret)
8619 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8620 out->adsp_hdlr_stream_handle = NULL;
8621 }
8622
Manish Dewangan21a850a2017-08-14 12:03:55 +05308623 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008624 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8625 out->ip_hdlr_handle = NULL;
8626 }
8627
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008628 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308629 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008630 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308631 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308632 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008633 if(ret != 0)
8634 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8635 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008636 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008637 out_standby(&stream->common);
8638
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008639 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008640 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008641 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008642 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008643 if (out->compr_config.codec != NULL)
8644 free(out->compr_config.codec);
8645 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008646
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308647 out->a2dp_compress_mute = false;
8648
Varun Balaraje49253e2017-07-06 19:48:56 +05308649 if (is_interactive_usecase(out->usecase))
8650 free_interactive_usecase(adev, out->usecase);
8651
Ashish Jain83a6cc22016-06-28 14:34:17 +05308652 if (out->convert_buffer != NULL) {
8653 free(out->convert_buffer);
8654 out->convert_buffer = NULL;
8655 }
8656
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008657 if (adev->voice_tx_output == out)
8658 adev->voice_tx_output = NULL;
8659
Aalique Grahame22e49102018-12-18 14:23:57 -08008660 error_log_destroy(out->error_log);
8661 out->error_log = NULL;
8662
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308663 if (adev->primary_output == out)
8664 adev->primary_output = NULL;
8665
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008666 pthread_cond_destroy(&out->cond);
8667 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008668 pthread_mutex_destroy(&out->pre_lock);
8669 pthread_mutex_destroy(&out->latch_lock);
8670 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008671
8672 pthread_mutex_lock(&adev->lock);
8673 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8674 if (out_ctxt != NULL) {
8675 list_remove(&out_ctxt->list);
8676 free(out_ctxt);
8677 } else {
8678 ALOGW("%s, output stream already closed", __func__);
8679 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008680 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008681 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008682 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008683}
8684
8685static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8686{
8687 struct audio_device *adev = (struct audio_device *)dev;
8688 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008689 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008690 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008691 int ret;
8692 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008693 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008694 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008695 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008696
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008697 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008698 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008699
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308700 if (!parms)
8701 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308702
Derek Chen6f293672019-04-01 01:40:24 -07008703 /* notify adev and input/output streams on the snd card status */
8704 adev_snd_mon_cb((void *)adev, parms);
8705
8706 list_for_each(node, &adev->active_outputs_list) {
8707 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8708 streams_output_ctxt_t,
8709 list);
8710 out_snd_mon_cb((void *)out_ctxt->output, parms);
8711 }
8712
8713 list_for_each(node, &adev->active_inputs_list) {
8714 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8715 streams_input_ctxt_t,
8716 list);
8717 in_snd_mon_cb((void *)in_ctxt->input, parms);
8718 }
8719
Zhou Songd6d71752019-05-21 18:08:51 +08008720 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308721 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8722 if (ret >= 0) {
8723 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008724 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308725 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008726 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308727 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008728 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008729 }
8730 }
8731
8732 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008733 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008734 if (!strncmp(value, "false", 5) &&
8735 audio_extn_a2dp_source_is_suspended()) {
8736 struct audio_usecase *usecase;
8737 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008738 list_for_each(node, &adev->usecase_list) {
8739 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008740 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008741 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008742 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008743 reassign_device_list(&usecase->stream.in->device_list,
8744 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008745 select_devices(adev, usecase->id);
8746 }
Zhou Songd6d71752019-05-21 18:08:51 +08008747 }
8748 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308749 }
8750
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008751 status = voice_set_parameters(adev, parms);
8752 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008753 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008755 status = platform_set_parameters(adev->platform, parms);
8756 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008757 goto done;
8758
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008759 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8760 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008761 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8763 adev->bluetooth_nrec = true;
8764 else
8765 adev->bluetooth_nrec = false;
8766 }
8767
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008768 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8769 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008770 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8771 adev->screen_off = false;
8772 else
8773 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008774 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008775 }
8776
Eric Laurent4b084132018-10-19 17:33:43 -07008777 ret = str_parms_get_int(parms, "rotation", &val);
8778 if (ret >= 0) {
8779 bool reverse_speakers = false;
8780 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8781 switch (val) {
8782 // FIXME: note that the code below assumes that the speakers are in the correct placement
8783 // relative to the user when the device is rotated 90deg from its default rotation. This
8784 // assumption is device-specific, not platform-specific like this code.
8785 case 270:
8786 reverse_speakers = true;
8787 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8788 break;
8789 case 0:
8790 case 180:
8791 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8792 break;
8793 case 90:
8794 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8795 break;
8796 default:
8797 ALOGE("%s: unexpected rotation of %d", __func__, val);
8798 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008799 }
Eric Laurent4b084132018-10-19 17:33:43 -07008800 if (status == 0) {
8801 // check and set swap
8802 // - check if orientation changed and speaker active
8803 // - set rotation and cache the rotation value
8804 adev->camera_orientation =
8805 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8806 if (!audio_extn_is_maxx_audio_enabled())
8807 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8808 }
8809 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008810
Mingming Yin514a8bc2014-07-29 15:22:21 -07008811 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8812 if (ret >= 0) {
8813 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8814 adev->bt_wb_speech_enabled = true;
8815 else
8816 adev->bt_wb_speech_enabled = false;
8817 }
8818
Zhou Song12c29502019-03-16 10:37:18 +08008819 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8820 if (ret >= 0) {
8821 val = atoi(value);
8822 adev->swb_speech_mode = val;
8823 }
8824
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008825 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8826 if (ret >= 0) {
8827 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308828 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008829 if (audio_is_output_device(val) &&
8830 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008831 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008832 platform_get_controller_stream_from_params(parms, &controller, &stream);
8833 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8834 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008835 if (ret < 0) {
8836 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308837 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008838 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008839 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308840 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008841 /*
8842 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8843 * Per AudioPolicyManager, USB device is higher priority than WFD.
8844 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8845 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8846 * starting voice call on USB
8847 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008848 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308849 if (ret >= 0)
8850 audio_extn_usb_add_device(device, atoi(value));
8851
Zhou Song6f862822017-11-06 17:27:57 +08008852 if (!audio_extn_usb_is_tunnel_supported()) {
8853 ALOGV("detected USB connect .. disable proxy");
8854 adev->allow_afe_proxy_usage = false;
8855 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008856 }
8857 }
8858
8859 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8860 if (ret >= 0) {
8861 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308862 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008863 /*
8864 * The HDMI / Displayport disconnect handling has been moved to
8865 * audio extension to ensure that its parameters are not
8866 * invalidated prior to updating sysfs of the disconnect event
8867 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8868 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308869 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008870 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308871 if (ret >= 0)
8872 audio_extn_usb_remove_device(device, atoi(value));
8873
Zhou Song6f862822017-11-06 17:27:57 +08008874 if (!audio_extn_usb_is_tunnel_supported()) {
8875 ALOGV("detected USB disconnect .. enable proxy");
8876 adev->allow_afe_proxy_usage = true;
8877 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008878 }
8879 }
8880
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008881 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008882
8883 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008884 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308885 struct audio_usecase *usecase;
8886 struct listnode *node;
8887 list_for_each(node, &adev->usecase_list) {
8888 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008889 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8890 continue;
8891
8892 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308893 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308894 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308895 ALOGD("Switching to speaker and muting the stream before select_devices");
8896 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308897 //force device switch to re configure encoder
8898 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308899 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008900 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308901 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008902 out_set_compr_volume(&usecase->stream.out->stream,
8903 usecase->stream.out->volume_l,
8904 usecase->stream.out->volume_r);
8905 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308906 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308907 break;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008908 } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
8909 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8910 if (usecase->stream.out->a2dp_compress_mute) {
8911 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8912 reassign_device_list(&usecase->stream.out->device_list,
8913 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8914 check_a2dp_restore_l(adev, usecase->stream.out, true);
8915 break;
8916 }
8917 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308918 }
8919 }
8920 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008921
8922 //handle vr audio setparam
8923 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8924 value, sizeof(value));
8925 if (ret >= 0) {
8926 ALOGI("Setting vr mode to be %s", value);
8927 if (!strncmp(value, "true", 4)) {
8928 adev->vr_audio_mode_enabled = true;
8929 ALOGI("Setting vr mode to true");
8930 } else if (!strncmp(value, "false", 5)) {
8931 adev->vr_audio_mode_enabled = false;
8932 ALOGI("Setting vr mode to false");
8933 } else {
8934 ALOGI("wrong vr mode set");
8935 }
8936 }
8937
Eric Laurent4b084132018-10-19 17:33:43 -07008938 //FIXME: to be replaced by proper video capture properties API
8939 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8940 if (ret >= 0) {
8941 int camera_facing = CAMERA_FACING_BACK;
8942 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8943 camera_facing = CAMERA_FACING_FRONT;
8944 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8945 camera_facing = CAMERA_FACING_BACK;
8946 else {
8947 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8948 goto done;
8949 }
8950 adev->camera_orientation =
8951 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8952 struct audio_usecase *usecase;
8953 struct listnode *node;
8954 list_for_each(node, &adev->usecase_list) {
8955 usecase = node_to_item(node, struct audio_usecase, list);
8956 struct stream_in *in = usecase->stream.in;
8957 if (usecase->type == PCM_CAPTURE && in != NULL &&
8958 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8959 select_devices(adev, in->usecase);
8960 }
8961 }
8962 }
8963
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308964 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008965done:
8966 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008967 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308968error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008969 ALOGV("%s: exit with code(%d)", __func__, status);
8970 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008971}
8972
8973static char* adev_get_parameters(const struct audio_hw_device *dev,
8974 const char *keys)
8975{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308976 ALOGD("%s:%s", __func__, keys);
8977
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008978 struct audio_device *adev = (struct audio_device *)dev;
8979 struct str_parms *reply = str_parms_create();
8980 struct str_parms *query = str_parms_create_str(keys);
8981 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308982 char value[256] = {0};
8983 int ret = 0;
8984
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008985 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008986 if (reply) {
8987 str_parms_destroy(reply);
8988 }
8989 if (query) {
8990 str_parms_destroy(query);
8991 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008992 ALOGE("adev_get_parameters: failed to create query or reply");
8993 return NULL;
8994 }
8995
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008996 //handle vr audio getparam
8997
8998 ret = str_parms_get_str(query,
8999 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9000 value, sizeof(value));
9001
9002 if (ret >= 0) {
9003 bool vr_audio_enabled = false;
9004 pthread_mutex_lock(&adev->lock);
9005 vr_audio_enabled = adev->vr_audio_mode_enabled;
9006 pthread_mutex_unlock(&adev->lock);
9007
9008 ALOGI("getting vr mode to %d", vr_audio_enabled);
9009
9010 if (vr_audio_enabled) {
9011 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9012 "true");
9013 goto exit;
9014 } else {
9015 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9016 "false");
9017 goto exit;
9018 }
9019 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009020
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009021 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009022 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009023 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009024 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009025 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009026 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309027 pthread_mutex_unlock(&adev->lock);
9028
Naresh Tannirud7205b62014-06-20 02:54:48 +05309029exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009030 str = str_parms_to_str(reply);
9031 str_parms_destroy(query);
9032 str_parms_destroy(reply);
9033
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309034 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009035 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036}
9037
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009038static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009039{
9040 return 0;
9041}
9042
9043static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9044{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009045 int ret;
9046 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009047
9048 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9049
Haynes Mathew George5191a852013-09-11 14:19:36 -07009050 pthread_mutex_lock(&adev->lock);
9051 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009052 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009053 pthread_mutex_unlock(&adev->lock);
9054 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009055}
9056
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009057static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9058 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009059{
9060 return -ENOSYS;
9061}
9062
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009063static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9064 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009065{
9066 return -ENOSYS;
9067}
9068
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009069static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9070 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009071{
9072 return -ENOSYS;
9073}
9074
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009075static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9076 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009077{
9078 return -ENOSYS;
9079}
9080
9081static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9082{
9083 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009084 struct listnode *node;
9085 struct audio_usecase *usecase = NULL;
9086 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009088 pthread_mutex_lock(&adev->lock);
9089 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309090 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9091 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009092 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009093 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309094 adev->current_call_output = adev->primary_output;
9095 voice_start_call(adev);
9096 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009097 (mode == AUDIO_MODE_NORMAL ||
9098 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009099 list_for_each(node, &adev->usecase_list) {
9100 usecase = node_to_item(node, struct audio_usecase, list);
9101 if (usecase->type == VOICE_CALL)
9102 break;
9103 }
9104 if (usecase &&
9105 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9106 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9107 true);
9108 if (ret != 0) {
9109 /* default service interval was successfully updated,
9110 reopen USB backend with new service interval */
9111 check_usecases_codec_backend(adev,
9112 usecase,
9113 usecase->out_snd_device);
9114 }
9115 }
9116
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009117 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009118 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009119 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009120 // restore device for other active usecases after stop call
9121 list_for_each(node, &adev->usecase_list) {
9122 usecase = node_to_item(node, struct audio_usecase, list);
9123 select_devices(adev, usecase->id);
9124 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009125 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009126 }
9127 pthread_mutex_unlock(&adev->lock);
9128 return 0;
9129}
9130
9131static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9132{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009133 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009134 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009135
9136 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009137 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009138 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009139
Derek Chend2530072014-11-24 12:39:14 -08009140 if (adev->ext_hw_plugin)
9141 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009142
9143 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009144 pthread_mutex_unlock(&adev->lock);
9145
9146 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009147}
9148
9149static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9150{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009151 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009152 return 0;
9153}
9154
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009155static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156 const struct audio_config *config)
9157{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009158 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009159
Aalique Grahame22e49102018-12-18 14:23:57 -08009160 /* Don't know if USB HIFI in this context so use true to be conservative */
9161 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9162 true /*is_usb_hifi */) != 0)
9163 return 0;
9164
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009165 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9166 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009167}
9168
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009169static bool adev_input_allow_hifi_record(struct audio_device *adev,
9170 audio_devices_t devices,
9171 audio_input_flags_t flags,
9172 audio_source_t source) {
9173 const bool allowed = true;
9174
9175 if (!audio_is_usb_in_device(devices))
9176 return !allowed;
9177
9178 switch (flags) {
9179 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009180 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009181 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9182 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009183 default:
9184 return !allowed;
9185 }
9186
9187 switch (source) {
9188 case AUDIO_SOURCE_DEFAULT:
9189 case AUDIO_SOURCE_MIC:
9190 case AUDIO_SOURCE_UNPROCESSED:
9191 break;
9192 default:
9193 return !allowed;
9194 }
9195
9196 switch (adev->mode) {
9197 case 0:
9198 break;
9199 default:
9200 return !allowed;
9201 }
9202
9203 return allowed;
9204}
9205
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009206static int adev_update_voice_comm_input_stream(struct stream_in *in,
9207 struct audio_config *config)
9208{
9209 bool valid_rate = (config->sample_rate == 8000 ||
9210 config->sample_rate == 16000 ||
9211 config->sample_rate == 32000 ||
9212 config->sample_rate == 48000);
9213 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9214
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009215 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009216 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009217 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9218 in->config = default_pcm_config_voip_copp;
9219 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9220 DEFAULT_VOIP_BUF_DURATION_MS,
9221 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009222 } else {
9223 ALOGW("%s No valid input in voip, use defaults"
9224 "sample rate %u, channel mask 0x%X",
9225 __func__, config->sample_rate, in->channel_mask);
9226 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009227 in->config.rate = config->sample_rate;
9228 in->sample_rate = config->sample_rate;
9229 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009230 //XXX needed for voice_extn_compress_voip_open_input_stream
9231 in->config.rate = config->sample_rate;
9232 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309233 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009234 voice_extn_compress_voip_is_active(in->dev)) &&
9235 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9236 valid_rate && valid_ch) {
9237 voice_extn_compress_voip_open_input_stream(in);
9238 // update rate entries to match config from AF
9239 in->config.rate = config->sample_rate;
9240 in->sample_rate = config->sample_rate;
9241 } else {
9242 ALOGW("%s compress voip not active, use defaults", __func__);
9243 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009244 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009245 return 0;
9246}
9247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009248static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009249 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009250 audio_devices_t devices,
9251 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009252 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309253 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009254 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009255 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009256{
9257 struct audio_device *adev = (struct audio_device *)dev;
9258 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009259 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009260 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009261 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309262 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009263 bool is_usb_dev = audio_is_usb_in_device(devices);
9264 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9265 devices,
9266 flags,
9267 source);
Andy Hung94320602018-10-29 18:31:12 -07009268 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9269 " sample_rate %u, channel_mask %#x, format %#x",
9270 __func__, flags, is_usb_dev, may_use_hifi_record,
9271 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309272
kunleizdff872d2018-08-20 14:40:33 +08009273 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009274 is_usb_dev = false;
9275 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9276 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9277 __func__, devices);
9278 }
9279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009280 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009281
9282 if (!(is_usb_dev && may_use_hifi_record)) {
9283 if (config->sample_rate == 0)
9284 config->sample_rate = 48000;
9285 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9286 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9287 if (config->format == AUDIO_FORMAT_DEFAULT)
9288 config->format = AUDIO_FORMAT_PCM_16_BIT;
9289
9290 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9291
Aalique Grahame22e49102018-12-18 14:23:57 -08009292 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9293 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009294 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009296
Rahul Sharma99770982019-03-06 17:05:26 +05309297 pthread_mutex_lock(&adev->lock);
9298 if (in_get_stream(adev, handle) != NULL) {
9299 ALOGW("%s, input stream already opened", __func__);
9300 ret = -EEXIST;
9301 }
9302 pthread_mutex_unlock(&adev->lock);
9303 if (ret)
9304 return ret;
9305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009306 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009307
9308 if (!in) {
9309 ALOGE("failed to allocate input stream");
9310 return -ENOMEM;
9311 }
9312
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309313 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309314 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9315 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009316 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009317 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009319 in->stream.common.get_sample_rate = in_get_sample_rate;
9320 in->stream.common.set_sample_rate = in_set_sample_rate;
9321 in->stream.common.get_buffer_size = in_get_buffer_size;
9322 in->stream.common.get_channels = in_get_channels;
9323 in->stream.common.get_format = in_get_format;
9324 in->stream.common.set_format = in_set_format;
9325 in->stream.common.standby = in_standby;
9326 in->stream.common.dump = in_dump;
9327 in->stream.common.set_parameters = in_set_parameters;
9328 in->stream.common.get_parameters = in_get_parameters;
9329 in->stream.common.add_audio_effect = in_add_audio_effect;
9330 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9331 in->stream.set_gain = in_set_gain;
9332 in->stream.read = in_read;
9333 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009334 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309335 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009336 in->stream.set_microphone_direction = in_set_microphone_direction;
9337 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009338 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009339
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009340 list_init(&in->device_list);
9341 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009342 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009343 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009344 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009345 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009346 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009347 in->bit_width = 16;
9348 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009349 in->direction = MIC_DIRECTION_UNSPECIFIED;
9350 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009351 list_init(&in->aec_list);
9352 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009353 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009354
Andy Hung94320602018-10-29 18:31:12 -07009355 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009356 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9357 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9358 /* Force channel config requested to mono if incall
9359 record is being requested for only uplink/downlink */
9360 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9361 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9362 ret = -EINVAL;
9363 goto err_open;
9364 }
9365 }
9366
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009367 if (is_usb_dev && may_use_hifi_record) {
9368 /* HiFi record selects an appropriate format, channel, rate combo
9369 depending on sink capabilities*/
9370 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9371 &config->format,
9372 &in->supported_formats[0],
9373 MAX_SUPPORTED_FORMATS,
9374 &config->channel_mask,
9375 &in->supported_channel_masks[0],
9376 MAX_SUPPORTED_CHANNEL_MASKS,
9377 &config->sample_rate,
9378 &in->supported_sample_rates[0],
9379 MAX_SUPPORTED_SAMPLE_RATES);
9380 if (ret != 0) {
9381 ret = -EINVAL;
9382 goto err_open;
9383 }
9384 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009385 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309386 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309387 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9388 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9389 in->config.format = PCM_FORMAT_S32_LE;
9390 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309391 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9392 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9393 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9394 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9395 bool ret_error = false;
9396 in->bit_width = 24;
9397 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9398 from HAL is 24_packed and 8_24
9399 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9400 24_packed return error indicating supported format is 24_packed
9401 *> In case of any other source requesting 24 bit or float return error
9402 indicating format supported is 16 bit only.
9403
9404 on error flinger will retry with supported format passed
9405 */
9406 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9407 (source != AUDIO_SOURCE_CAMCORDER)) {
9408 config->format = AUDIO_FORMAT_PCM_16_BIT;
9409 if (config->sample_rate > 48000)
9410 config->sample_rate = 48000;
9411 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009412 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9413 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309414 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9415 ret_error = true;
9416 }
9417
9418 if (ret_error) {
9419 ret = -EINVAL;
9420 goto err_open;
9421 }
9422 }
9423
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009424 in->channel_mask = config->channel_mask;
9425 in->format = config->format;
9426
9427 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309428
9429 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9430 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9431 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9432 else {
9433 ret = -EINVAL;
9434 goto err_open;
9435 }
9436 }
9437
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009438 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309439 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9440 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009441 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9442 is_low_latency = true;
9443#if LOW_LATENCY_CAPTURE_USE_CASE
9444 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9445#endif
9446 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009447 if (!in->realtime) {
9448 in->config = pcm_config_audio_capture;
9449 frame_size = audio_stream_in_frame_size(&in->stream);
9450 buffer_size = get_input_buffer_size(config->sample_rate,
9451 config->format,
9452 channel_count,
9453 is_low_latency);
9454 in->config.period_size = buffer_size / frame_size;
9455 in->config.rate = config->sample_rate;
9456 in->af_period_multiplier = 1;
9457 } else {
9458 // period size is left untouched for rt mode playback
9459 in->config = pcm_config_audio_capture_rt;
9460 in->af_period_multiplier = af_period_multiplier;
9461 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009462 }
9463
9464 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9465 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9466 in->realtime = 0;
9467 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9468 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009469 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009470 in->stream.start = in_start;
9471 in->stream.stop = in_stop;
9472 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9473 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009474 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009475 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009476 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9477 in->config = pcm_config_audio_capture;
9478 frame_size = audio_stream_in_frame_size(&in->stream);
9479 buffer_size = get_input_buffer_size(config->sample_rate,
9480 config->format,
9481 channel_count,
9482 false /*is_low_latency*/);
9483 in->config.period_size = buffer_size / frame_size;
9484 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009485 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009486 switch (config->format) {
9487 case AUDIO_FORMAT_PCM_32_BIT:
9488 in->bit_width = 32;
9489 break;
9490 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9491 case AUDIO_FORMAT_PCM_8_24_BIT:
9492 in->bit_width = 24;
9493 break;
9494 default:
9495 in->bit_width = 16;
9496 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009497 } else if (is_single_device_type_equal(&in->device_list,
9498 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9499 is_single_device_type_equal(&in->device_list,
9500 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009501 if (config->sample_rate == 0)
9502 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9503 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9504 config->sample_rate != 8000) {
9505 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9506 ret = -EINVAL;
9507 goto err_open;
9508 }
9509 if (config->format == AUDIO_FORMAT_DEFAULT)
9510 config->format = AUDIO_FORMAT_PCM_16_BIT;
9511 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9512 config->format = AUDIO_FORMAT_PCM_16_BIT;
9513 ret = -EINVAL;
9514 goto err_open;
9515 }
9516
9517 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009518 if (adev->ha_proxy_enable &&
9519 is_single_device_type_equal(&in->device_list,
9520 AUDIO_DEVICE_IN_TELEPHONY_RX))
9521 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009522 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009523 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009524 in->af_period_multiplier = 1;
9525 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9526 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9527 (config->sample_rate == 8000 ||
9528 config->sample_rate == 16000 ||
9529 config->sample_rate == 32000 ||
9530 config->sample_rate == 48000) &&
9531 channel_count == 1) {
9532 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9533 in->config = pcm_config_audio_capture;
9534 frame_size = audio_stream_in_frame_size(&in->stream);
9535 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9536 config->sample_rate,
9537 config->format,
9538 channel_count, false /*is_low_latency*/);
9539 in->config.period_size = buffer_size / frame_size;
9540 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9541 in->config.rate = config->sample_rate;
9542 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009543 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309544 int ret_val;
9545 pthread_mutex_lock(&adev->lock);
9546 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9547 in, config, &channel_mask_updated);
9548 pthread_mutex_unlock(&adev->lock);
9549
9550 if (!ret_val) {
9551 if (channel_mask_updated == true) {
9552 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9553 __func__, config->channel_mask);
9554 ret = -EINVAL;
9555 goto err_open;
9556 }
9557 ALOGD("%s: created multi-channel session succesfully",__func__);
9558 } else if (audio_extn_compr_cap_enabled() &&
9559 audio_extn_compr_cap_format_supported(config->format) &&
9560 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9561 audio_extn_compr_cap_init(in);
9562 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309563 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309564 if (ret)
9565 goto err_open;
9566 } else {
9567 in->config = pcm_config_audio_capture;
9568 in->config.rate = config->sample_rate;
9569 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309570 in->format = config->format;
9571 frame_size = audio_stream_in_frame_size(&in->stream);
9572 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009573 config->format,
9574 channel_count,
9575 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009576 /* prevent division-by-zero */
9577 if (frame_size == 0) {
9578 ALOGE("%s: Error frame_size==0", __func__);
9579 ret = -EINVAL;
9580 goto err_open;
9581 }
9582
Revathi Uddarajud2634032017-12-07 14:42:34 +05309583 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009584 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009585
Revathi Uddarajud2634032017-12-07 14:42:34 +05309586 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9587 /* optionally use VOIP usecase depending on config(s) */
9588 ret = adev_update_voice_comm_input_stream(in, config);
9589 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009590
Revathi Uddarajud2634032017-12-07 14:42:34 +05309591 if (ret) {
9592 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9593 goto err_open;
9594 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009595 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309596
9597 /* assign concurrent capture usecase if record has to caried out from
9598 * actual hardware input source */
9599 if (audio_extn_is_concurrent_capture_enabled() &&
9600 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309601 /* Acquire lock to avoid two concurrent use cases initialized to
9602 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009603
Samyak Jainc37062f2019-04-25 18:41:06 +05309604 if (in->usecase == USECASE_AUDIO_RECORD) {
9605 pthread_mutex_lock(&adev->lock);
9606 if (!(adev->pcm_record_uc_state)) {
9607 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9608 adev->pcm_record_uc_state = 1;
9609 pthread_mutex_unlock(&adev->lock);
9610 } else {
9611 pthread_mutex_unlock(&adev->lock);
9612 /* Assign compress record use case for second record */
9613 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9614 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9615 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9616 if (audio_extn_cin_applicable_stream(in)) {
9617 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309618 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309619 if (ret)
9620 goto err_open;
9621 }
9622 }
9623 }
kunleiz28c73e72019-03-27 17:24:04 +08009624 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009625 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309626 if (audio_extn_ssr_get_stream() != in)
9627 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009628
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009629 in->sample_rate = in->config.rate;
9630
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309631 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9632 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009633 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009634 in->sample_rate, in->bit_width,
9635 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309636 register_format(in->format, in->supported_formats);
9637 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9638 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309639
Aalique Grahame22e49102018-12-18 14:23:57 -08009640 in->error_log = error_log_create(
9641 ERROR_LOG_ENTRIES,
9642 1000000000 /* aggregate consecutive identical errors within one second */);
9643
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009644 /* This stream could be for sound trigger lab,
9645 get sound trigger pcm if present */
9646 audio_extn_sound_trigger_check_and_get_session(in);
9647
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309648 lock_input_stream(in);
9649 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9650 pthread_mutex_lock(&adev->lock);
9651 in->card_status = adev->card_status;
9652 pthread_mutex_unlock(&adev->lock);
9653 pthread_mutex_unlock(&in->lock);
9654
Aalique Grahame22e49102018-12-18 14:23:57 -08009655 stream_app_type_cfg_init(&in->app_type_cfg);
9656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009657 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009658
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009659 ret = io_streams_map_insert(adev, &in->stream.common,
9660 handle, AUDIO_PATCH_HANDLE_NONE);
9661 if (ret != 0)
9662 goto err_open;
9663
Derek Chenf939fb72018-11-13 13:34:41 -08009664 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9665 calloc(1, sizeof(streams_input_ctxt_t));
9666 if (in_ctxt == NULL) {
9667 ALOGE("%s fail to allocate input ctxt", __func__);
9668 ret = -ENOMEM;
9669 goto err_open;
9670 }
9671 in_ctxt->input = in;
9672
9673 pthread_mutex_lock(&adev->lock);
9674 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9675 pthread_mutex_unlock(&adev->lock);
9676
Eric Laurent994a6932013-07-17 11:51:42 -07009677 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009678 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009679
9680err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309681 if (in->usecase == USECASE_AUDIO_RECORD) {
9682 pthread_mutex_lock(&adev->lock);
9683 adev->pcm_record_uc_state = 0;
9684 pthread_mutex_unlock(&adev->lock);
9685 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009686 free(in);
9687 *stream_in = NULL;
9688 return ret;
9689}
9690
9691static void adev_close_input_stream(struct audio_hw_device *dev,
9692 struct audio_stream_in *stream)
9693{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009694 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009695 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009696 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309697
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309698 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009699
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009700 if (in == NULL) {
9701 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9702 return;
9703 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009704 io_streams_map_remove(adev, in->capture_handle);
9705
kunleiz70e57612018-12-28 17:50:23 +08009706 /* must deregister from sndmonitor first to prevent races
9707 * between the callback and close_stream
9708 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309709 audio_extn_snd_mon_unregister_listener(stream);
9710
kunleiz70e57612018-12-28 17:50:23 +08009711 /* Disable echo reference if there are no active input, hfp call
9712 * and sound trigger while closing input stream
9713 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009714 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009715 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009716 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9717 struct listnode out_devices;
9718 list_init(&out_devices);
9719 platform_set_echo_reference(adev, false, &out_devices);
9720 } else
kunleiz70e57612018-12-28 17:50:23 +08009721 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309722
Weiyin Jiang2995f662019-04-17 14:25:12 +08009723 error_log_destroy(in->error_log);
9724 in->error_log = NULL;
9725
Pallavid7c7a272018-01-16 11:22:55 +05309726
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009727 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309728 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009729 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309730 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009731 if (ret != 0)
9732 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9733 __func__, ret);
9734 } else
9735 in_standby(&stream->common);
9736
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009737 pthread_mutex_destroy(&in->lock);
9738 pthread_mutex_destroy(&in->pre_lock);
9739
Revathi Uddarajud2634032017-12-07 14:42:34 +05309740 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309741 if (in->usecase == USECASE_AUDIO_RECORD) {
9742 adev->pcm_record_uc_state = 0;
9743 }
9744
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009745 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9746 adev->enable_voicerx = false;
9747 }
9748
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009749 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009750 audio_extn_ssr_deinit();
9751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009752
Garmond Leunge2433c32017-09-28 21:51:22 -07009753 if (audio_extn_ffv_get_stream() == in) {
9754 audio_extn_ffv_stream_deinit();
9755 }
9756
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309757 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009758 audio_extn_compr_cap_format_supported(in->config.format))
9759 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309760
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309761 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309762 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009763
Mingming Yinfd7607b2016-01-22 12:48:44 -08009764 if (in->is_st_session) {
9765 ALOGV("%s: sound trigger pcm stop lab", __func__);
9766 audio_extn_sound_trigger_stop_lab(in);
9767 }
Derek Chenf939fb72018-11-13 13:34:41 -08009768 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9769 if (in_ctxt != NULL) {
9770 list_remove(&in_ctxt->list);
9771 free(in_ctxt);
9772 } else {
9773 ALOGW("%s, input stream already closed", __func__);
9774 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009775 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309776 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009777 return;
9778}
9779
Aalique Grahame22e49102018-12-18 14:23:57 -08009780/* verifies input and output devices and their capabilities.
9781 *
9782 * This verification is required when enabling extended bit-depth or
9783 * sampling rates, as not all qcom products support it.
9784 *
9785 * Suitable for calling only on initialization such as adev_open().
9786 * It fills the audio_device use_case_table[] array.
9787 *
9788 * Has a side-effect that it needs to configure audio routing / devices
9789 * in order to power up the devices and read the device parameters.
9790 * It does not acquire any hw device lock. Should restore the devices
9791 * back to "normal state" upon completion.
9792 */
9793static int adev_verify_devices(struct audio_device *adev)
9794{
9795 /* enumeration is a bit difficult because one really wants to pull
9796 * the use_case, device id, etc from the hidden pcm_device_table[].
9797 * In this case there are the following use cases and device ids.
9798 *
9799 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9800 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9801 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9802 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9803 * [USECASE_AUDIO_RECORD] = {0, 0},
9804 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9805 * [USECASE_VOICE_CALL] = {2, 2},
9806 *
9807 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9808 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9809 */
9810
9811 /* should be the usecases enabled in adev_open_input_stream() */
9812 static const int test_in_usecases[] = {
9813 USECASE_AUDIO_RECORD,
9814 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9815 };
9816 /* should be the usecases enabled in adev_open_output_stream()*/
9817 static const int test_out_usecases[] = {
9818 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9819 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9820 };
9821 static const usecase_type_t usecase_type_by_dir[] = {
9822 PCM_PLAYBACK,
9823 PCM_CAPTURE,
9824 };
9825 static const unsigned flags_by_dir[] = {
9826 PCM_OUT,
9827 PCM_IN,
9828 };
9829
9830 size_t i;
9831 unsigned dir;
9832 const unsigned card_id = adev->snd_card;
9833
9834 for (dir = 0; dir < 2; ++dir) {
9835 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9836 const unsigned flags_dir = flags_by_dir[dir];
9837 const size_t testsize =
9838 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9839 const int *testcases =
9840 dir ? test_in_usecases : test_out_usecases;
9841 const audio_devices_t audio_device =
9842 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9843
9844 for (i = 0; i < testsize; ++i) {
9845 const audio_usecase_t audio_usecase = testcases[i];
9846 int device_id;
9847 struct pcm_params **pparams;
9848 struct stream_out out;
9849 struct stream_in in;
9850 struct audio_usecase uc_info;
9851 int retval;
9852
9853 pparams = &adev->use_case_table[audio_usecase];
9854 pcm_params_free(*pparams); /* can accept null input */
9855 *pparams = NULL;
9856
9857 /* find the device ID for the use case (signed, for error) */
9858 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9859 if (device_id < 0)
9860 continue;
9861
9862 /* prepare structures for device probing */
9863 memset(&uc_info, 0, sizeof(uc_info));
9864 uc_info.id = audio_usecase;
9865 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009866 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009867 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009868 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009869 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009870 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009871 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9872 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009873 }
9874 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009875 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009876 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009877 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009878 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009879 uc_info.in_snd_device = SND_DEVICE_NONE;
9880 uc_info.out_snd_device = SND_DEVICE_NONE;
9881 list_add_tail(&adev->usecase_list, &uc_info.list);
9882
9883 /* select device - similar to start_(in/out)put_stream() */
9884 retval = select_devices(adev, audio_usecase);
9885 if (retval >= 0) {
9886 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9887#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009888 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009889 if (*pparams) {
9890 ALOGV("%s: (%s) card %d device %d", __func__,
9891 dir ? "input" : "output", card_id, device_id);
9892 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9893 } else {
9894 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9895 }
9896#endif
9897 }
9898
9899 /* deselect device - similar to stop_(in/out)put_stream() */
9900 /* 1. Get and set stream specific mixer controls */
9901 retval = disable_audio_route(adev, &uc_info);
9902 /* 2. Disable the rx device */
9903 retval = disable_snd_device(adev,
9904 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9905 list_remove(&uc_info.list);
9906 }
9907 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009908 return 0;
9909}
9910
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009911int update_patch(unsigned int num_sources,
9912 const struct audio_port_config *sources,
9913 unsigned int num_sinks,
9914 const struct audio_port_config *sinks,
9915 audio_patch_handle_t handle,
9916 struct audio_patch_info *p_info,
9917 patch_type_t patch_type, bool new_patch)
9918{
9919 ALOGD("%s: enter", __func__);
9920
9921 if (p_info == NULL) {
9922 ALOGE("%s: Invalid patch pointer", __func__);
9923 return -EINVAL;
9924 }
9925
9926 if (new_patch) {
9927 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9928 if (p_info->patch == NULL) {
9929 ALOGE("%s: Could not allocate patch", __func__);
9930 return -ENOMEM;
9931 }
9932 }
9933
9934 p_info->patch->id = handle;
9935 p_info->patch->num_sources = num_sources;
9936 p_info->patch->num_sinks = num_sinks;
9937
9938 for (int i = 0; i < num_sources; i++)
9939 p_info->patch->sources[i] = sources[i];
9940 for (int i = 0; i < num_sinks; i++)
9941 p_info->patch->sinks[i] = sinks[i];
9942
9943 p_info->patch_type = patch_type;
9944 return 0;
9945}
9946
9947audio_patch_handle_t generate_patch_handle()
9948{
9949 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9950 if (++patch_handle < 0)
9951 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9952 return patch_handle;
9953}
9954
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309955int adev_create_audio_patch(struct audio_hw_device *dev,
9956 unsigned int num_sources,
9957 const struct audio_port_config *sources,
9958 unsigned int num_sinks,
9959 const struct audio_port_config *sinks,
9960 audio_patch_handle_t *handle)
9961{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009962 int ret = 0;
9963 struct audio_device *adev = (struct audio_device *)dev;
9964 struct audio_patch_info *p_info = NULL;
9965 patch_type_t patch_type = PATCH_NONE;
9966 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9967 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9968 struct audio_stream_info *s_info = NULL;
9969 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009970 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009971 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9972 bool new_patch = false;
9973 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309974
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009975 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9976 num_sources, num_sinks, *handle);
9977
9978 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9979 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9980 ALOGE("%s: Invalid patch arguments", __func__);
9981 ret = -EINVAL;
9982 goto done;
9983 }
9984
9985 if (num_sources > 1) {
9986 ALOGE("%s: Multiple sources are not supported", __func__);
9987 ret = -EINVAL;
9988 goto done;
9989 }
9990
9991 if (sources == NULL || sinks == NULL) {
9992 ALOGE("%s: Invalid sources or sinks port config", __func__);
9993 ret = -EINVAL;
9994 goto done;
9995 }
9996
9997 ALOGV("%s: source role %d, source type %d", __func__,
9998 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009999 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010000
10001 // Populate source/sink information and fetch stream info
10002 switch (sources[0].type) {
10003 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10004 device_type = sources[0].ext.device.type;
10005 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010006 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010007 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10008 patch_type = PATCH_CAPTURE;
10009 io_handle = sinks[0].ext.mix.handle;
10010 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010011 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010012 __func__, device_type, io_handle);
10013 } else {
10014 // Device to device patch is not implemented.
10015 // This space will need changes if audio HAL
10016 // handles device to device patches in the future.
10017 patch_type = PATCH_DEVICE_LOOPBACK;
10018 }
10019 break;
10020 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10021 io_handle = sources[0].ext.mix.handle;
10022 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010023 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010025 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010026 }
10027 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010028 ALOGD("%s: Playback patch from mix handle %d to device %x",
10029 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010030 break;
10031 case AUDIO_PORT_TYPE_SESSION:
10032 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010033 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10034 ret = -EINVAL;
10035 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010036 }
10037
10038 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010039
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010040 // Generate patch info and update patch
10041 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010042 *handle = generate_patch_handle();
10043 p_info = (struct audio_patch_info *)
10044 calloc(1, sizeof(struct audio_patch_info));
10045 if (p_info == NULL) {
10046 ALOGE("%s: Failed to allocate memory", __func__);
10047 pthread_mutex_unlock(&adev->lock);
10048 ret = -ENOMEM;
10049 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010050 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010051 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010052 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010053 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010054 if (p_info == NULL) {
10055 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10056 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010057 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010058 ret = -EINVAL;
10059 goto done;
10060 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010061 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010062 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010063 *handle, p_info, patch_type, new_patch);
10064
10065 // Fetch stream info of associated mix for playback or capture patches
10066 if (p_info->patch_type == PATCH_PLAYBACK ||
10067 p_info->patch_type == PATCH_CAPTURE) {
10068 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10069 if (s_info == NULL) {
10070 ALOGE("%s: Failed to obtain stream info", __func__);
10071 if (new_patch)
10072 free(p_info);
10073 pthread_mutex_unlock(&adev->lock);
10074 ret = -EINVAL;
10075 goto done;
10076 }
10077 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10078 s_info->patch_handle = *handle;
10079 stream = s_info->stream;
10080 }
10081 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010082
10083 // Update routing for stream
10084 if (stream != NULL) {
10085 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010086 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010087 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010088 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010089 if (ret < 0) {
10090 pthread_mutex_lock(&adev->lock);
10091 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10092 if (new_patch)
10093 free(p_info);
10094 pthread_mutex_unlock(&adev->lock);
10095 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10096 goto done;
10097 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010098 }
10099
10100 // Add new patch to patch map
10101 if (!ret && new_patch) {
10102 pthread_mutex_lock(&adev->lock);
10103 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010105 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010106 }
10107
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010108done:
10109 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010110 num_sources,
10111 sources,
10112 num_sinks,
10113 sinks,
10114 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010115 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010116 num_sources,
10117 sources,
10118 num_sinks,
10119 sinks,
10120 handle);
10121 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010122}
10123
10124int adev_release_audio_patch(struct audio_hw_device *dev,
10125 audio_patch_handle_t handle)
10126{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010127 struct audio_device *adev = (struct audio_device *) dev;
10128 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010130 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010131
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010132 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10133 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10134 ret = -EINVAL;
10135 goto done;
10136 }
10137
10138 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010139 pthread_mutex_lock(&adev->lock);
10140 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010141 if (p_info == NULL) {
10142 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010143 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144 ret = -EINVAL;
10145 goto done;
10146 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 struct audio_patch *patch = p_info->patch;
10148 if (patch == NULL) {
10149 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010150 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010151 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 goto done;
10153 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010154 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10155 switch (patch->sources[0].type) {
10156 case AUDIO_PORT_TYPE_MIX:
10157 io_handle = patch->sources[0].ext.mix.handle;
10158 break;
10159 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010160 if (p_info->patch_type == PATCH_CAPTURE)
10161 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 break;
10163 case AUDIO_PORT_TYPE_SESSION:
10164 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010165 pthread_mutex_unlock(&adev->lock);
10166 ret = -EINVAL;
10167 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010168 }
10169
10170 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010171 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010172 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010173 if (patch_type == PATCH_PLAYBACK ||
10174 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010175 struct audio_stream_info *s_info =
10176 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10177 if (s_info == NULL) {
10178 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10179 pthread_mutex_unlock(&adev->lock);
10180 goto done;
10181 }
10182 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10183 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010184 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010185 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010186
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010188 struct listnode devices;
10189 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010190 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010191 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010192 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010193 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010194 }
10195
10196 if (ret < 0)
10197 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10198
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010199done:
10200 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10201 audio_extn_auto_hal_release_audio_patch(dev, handle);
10202
10203 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010204 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010205}
10206
10207int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10208{
Derek Chenf13dd492018-11-13 14:53:51 -080010209 int ret = 0;
10210
10211 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10212 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10213 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010214}
10215
10216int adev_set_audio_port_config(struct audio_hw_device *dev,
10217 const struct audio_port_config *config)
10218{
Derek Chenf13dd492018-11-13 14:53:51 -080010219 int ret = 0;
10220
10221 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10222 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10223 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010224}
10225
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010226static int adev_dump(const audio_hw_device_t *device __unused,
10227 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010228{
10229 return 0;
10230}
10231
10232static int adev_close(hw_device_t *device)
10233{
Aalique Grahame22e49102018-12-18 14:23:57 -080010234 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010235 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010236
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010237 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010238 return 0;
10239
10240 pthread_mutex_lock(&adev_init_lock);
10241
10242 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010243 if (audio_extn_spkr_prot_is_enabled())
10244 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010245 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010246 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010247 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010248 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010249 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010250 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010251 audio_extn_utils_release_streams_cfg_lists(
10252 &adev->streams_output_cfg_list,
10253 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010254 if (audio_extn_qap_is_enabled())
10255 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010256 if (audio_extn_qaf_is_enabled())
10257 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010258 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010259 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010260 free(adev->snd_dev_ref_cnt);
10261 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010262 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10263 pcm_params_free(adev->use_case_table[i]);
10264 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010265 if (adev->adm_deinit)
10266 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010267 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010268 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010269 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010270 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010271 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010272 if (adev->device_cfg_params) {
10273 free(adev->device_cfg_params);
10274 adev->device_cfg_params = NULL;
10275 }
Derek Chend2530072014-11-24 12:39:14 -080010276 if(adev->ext_hw_plugin)
10277 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010278 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010279 free_map(adev->patch_map);
10280 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010281 free(device);
10282 adev = NULL;
10283 }
10284 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010285 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010286 return 0;
10287}
10288
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010289/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10290 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10291 * just that it _might_ work.
10292 */
10293static int period_size_is_plausible_for_low_latency(int period_size)
10294{
10295 switch (period_size) {
10296 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010297 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010298 case 240:
10299 case 320:
10300 case 480:
10301 return 1;
10302 default:
10303 return 0;
10304 }
10305}
10306
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010307static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10308{
10309 bool is_snd_card_status = false;
10310 bool is_ext_device_status = false;
10311 char value[32];
10312 int card = -1;
10313 card_status_t status;
10314
10315 if (cookie != adev || !parms)
10316 return;
10317
10318 if (!parse_snd_card_status(parms, &card, &status)) {
10319 is_snd_card_status = true;
10320 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10321 is_ext_device_status = true;
10322 } else {
10323 // not a valid event
10324 return;
10325 }
10326
10327 pthread_mutex_lock(&adev->lock);
10328 if (card == adev->snd_card || is_ext_device_status) {
10329 if (is_snd_card_status && adev->card_status != status) {
10330 adev->card_status = status;
10331 platform_snd_card_update(adev->platform, status);
10332 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010333 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010334 if (status == CARD_STATUS_OFFLINE)
10335 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010336 } else if (is_ext_device_status) {
10337 platform_set_parameters(adev->platform, parms);
10338 }
10339 }
10340 pthread_mutex_unlock(&adev->lock);
10341 return;
10342}
10343
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010344/* adev lock held */
10345int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010346{
10347 struct audio_usecase *uc_info;
10348 float left_p;
10349 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010350 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010351
10352 uc_info = get_usecase_from_list(adev, out->usecase);
10353 if (uc_info == NULL) {
10354 ALOGE("%s: Could not find the usecase (%d) in the list",
10355 __func__, out->usecase);
10356 return -EINVAL;
10357 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010358 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010359
10360 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10361 out->usecase, use_case_table[out->usecase]);
10362
10363 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010364 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010365 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010366 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010367 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010368 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10369 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010370 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010371 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10372 if (out->a2dp_compress_mute) {
10373 out->a2dp_compress_mute = false;
10374 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10375 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010376 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010377 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010378 out->muted = false;
10379 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010380 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010381 pthread_mutex_lock(&out->latch_lock);
Zhou Songc576a452019-09-09 14:17:40 +080010382 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10383 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010384 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010385 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010386 assign_devices(&devices, &out->device_list);
10387 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010388 left_p = out->volume_l;
10389 right_p = out->volume_r;
10390 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10391 compress_pause(out->compr);
10392 out_set_compr_volume(&out->stream, (float)0, (float)0);
10393 out->a2dp_compress_mute = true;
10394 select_devices(adev, out->usecase);
10395 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10396 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010397 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010398 out->volume_l = left_p;
10399 out->volume_r = right_p;
10400 }
Zhou Songc576a452019-09-09 14:17:40 +080010401 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010402 // mute for non offloaded streams
10403 if (audio_extn_a2dp_source_is_suspended()) {
10404 out->muted = true;
10405 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010406 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010407 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010408 }
10409 ALOGV("%s: exit", __func__);
10410 return 0;
10411}
10412
Haynes Mathew George01156f92018-04-13 15:29:54 -070010413void adev_on_battery_status_changed(bool charging)
10414{
10415 pthread_mutex_lock(&adev->lock);
10416 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10417 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010418 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010419 pthread_mutex_unlock(&adev->lock);
10420}
10421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010422static int adev_open(const hw_module_t *module, const char *name,
10423 hw_device_t **device)
10424{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010425 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010426 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010427 char mixer_ctl_name[128] = {0};
10428 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010429
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010430 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010431 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10432
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010433 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010434 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010435 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010436 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010437 ALOGD("%s: returning existing instance of adev", __func__);
10438 ALOGD("%s: exit", __func__);
10439 pthread_mutex_unlock(&adev_init_lock);
10440 return 0;
10441 }
10442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010443 adev = calloc(1, sizeof(struct audio_device));
10444
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010445 if (!adev) {
10446 pthread_mutex_unlock(&adev_init_lock);
10447 return -ENOMEM;
10448 }
10449
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010450 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10451
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010452 // register audio ext hidl at the earliest
10453 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010454#ifdef DYNAMIC_LOG_ENABLED
10455 register_for_dynamic_logging("hal");
10456#endif
10457
Derek Chenf939fb72018-11-13 13:34:41 -080010458 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010459 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010460 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10461 maj_version = atoi(value);
10462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010463 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010464 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010465 adev->device.common.module = (struct hw_module_t *)module;
10466 adev->device.common.close = adev_close;
10467
10468 adev->device.init_check = adev_init_check;
10469 adev->device.set_voice_volume = adev_set_voice_volume;
10470 adev->device.set_master_volume = adev_set_master_volume;
10471 adev->device.get_master_volume = adev_get_master_volume;
10472 adev->device.set_master_mute = adev_set_master_mute;
10473 adev->device.get_master_mute = adev_get_master_mute;
10474 adev->device.set_mode = adev_set_mode;
10475 adev->device.set_mic_mute = adev_set_mic_mute;
10476 adev->device.get_mic_mute = adev_get_mic_mute;
10477 adev->device.set_parameters = adev_set_parameters;
10478 adev->device.get_parameters = adev_get_parameters;
10479 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10480 adev->device.open_output_stream = adev_open_output_stream;
10481 adev->device.close_output_stream = adev_close_output_stream;
10482 adev->device.open_input_stream = adev_open_input_stream;
10483 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010484 adev->device.create_audio_patch = adev_create_audio_patch;
10485 adev->device.release_audio_patch = adev_release_audio_patch;
10486 adev->device.get_audio_port = adev_get_audio_port;
10487 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010488 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010489 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010490
10491 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010492 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010493 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010494 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010495 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010496 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010497 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010498 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010499 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010500 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010501 /* Init audio and voice feature */
10502 audio_extn_feature_init();
10503 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010504 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010505 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010506 list_init(&adev->active_inputs_list);
10507 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010508 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010509 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10510 audio_extn_utils_hash_eq);
10511 if (!adev->io_streams_map) {
10512 ALOGE("%s: Could not create io streams map", __func__);
10513 ret = -ENOMEM;
10514 goto adev_open_err;
10515 }
10516 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10517 audio_extn_utils_hash_eq);
10518 if (!adev->patch_map) {
10519 ALOGE("%s: Could not create audio patch map", __func__);
10520 ret = -ENOMEM;
10521 goto adev_open_err;
10522 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010523 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010524 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010525 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010526 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010527 adev->perf_lock_opts[0] = 0x101;
10528 adev->perf_lock_opts[1] = 0x20E;
10529 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010530 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010531 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010532 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010533 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010534 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010535
Zhou Song68ebc352019-12-05 17:11:15 +080010536 audio_extn_perf_lock_init();
10537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010538 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010539 adev->platform = platform_init(adev);
10540 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010541 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010542 ret = -EINVAL;
10543 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010544 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010545
Aalique Grahame22e49102018-12-18 14:23:57 -080010546 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010547 if (audio_extn_qap_is_enabled()) {
10548 ret = audio_extn_qap_init(adev);
10549 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010550 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010551 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010552 }
10553 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10554 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10555 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010556
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010557 if (audio_extn_qaf_is_enabled()) {
10558 ret = audio_extn_qaf_init(adev);
10559 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010560 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010561 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010562 }
10563
10564 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10565 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10566 }
10567
Derek Chenae7b0342019-02-08 15:17:04 -080010568 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010569 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10570
Eric Laurentc4aef752013-09-12 17:45:53 -070010571 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10572 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10573 if (adev->visualizer_lib == NULL) {
10574 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10575 } else {
10576 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10577 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010578 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010579 "visualizer_hal_start_output");
10580 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010581 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010582 "visualizer_hal_stop_output");
10583 }
10584 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010585 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010586 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010587 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010588 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010589 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010590 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010591
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010592 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10593 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10594 if (adev->offload_effects_lib == NULL) {
10595 ALOGE("%s: DLOPEN failed for %s", __func__,
10596 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10597 } else {
10598 ALOGV("%s: DLOPEN successful for %s", __func__,
10599 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10600 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010601 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010602 "offload_effects_bundle_hal_start_output");
10603 adev->offload_effects_stop_output =
10604 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10605 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010606 adev->offload_effects_set_hpx_state =
10607 (int (*)(bool))dlsym(adev->offload_effects_lib,
10608 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010609 adev->offload_effects_get_parameters =
10610 (void (*)(struct str_parms *, struct str_parms *))
10611 dlsym(adev->offload_effects_lib,
10612 "offload_effects_bundle_get_parameters");
10613 adev->offload_effects_set_parameters =
10614 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10615 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010616 }
10617 }
10618
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010619 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10620 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10621 if (adev->adm_lib == NULL) {
10622 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10623 } else {
10624 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10625 adev->adm_init = (adm_init_t)
10626 dlsym(adev->adm_lib, "adm_init");
10627 adev->adm_deinit = (adm_deinit_t)
10628 dlsym(adev->adm_lib, "adm_deinit");
10629 adev->adm_register_input_stream = (adm_register_input_stream_t)
10630 dlsym(adev->adm_lib, "adm_register_input_stream");
10631 adev->adm_register_output_stream = (adm_register_output_stream_t)
10632 dlsym(adev->adm_lib, "adm_register_output_stream");
10633 adev->adm_deregister_stream = (adm_deregister_stream_t)
10634 dlsym(adev->adm_lib, "adm_deregister_stream");
10635 adev->adm_request_focus = (adm_request_focus_t)
10636 dlsym(adev->adm_lib, "adm_request_focus");
10637 adev->adm_abandon_focus = (adm_abandon_focus_t)
10638 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010639 adev->adm_set_config = (adm_set_config_t)
10640 dlsym(adev->adm_lib, "adm_set_config");
10641 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10642 dlsym(adev->adm_lib, "adm_request_focus_v2");
10643 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10644 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10645 adev->adm_on_routing_change = (adm_on_routing_change_t)
10646 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010647 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10648 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010649 }
10650 }
10651
Aalique Grahame22e49102018-12-18 14:23:57 -080010652 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010653 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010654 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010655 //initialize this to false for now,
10656 //this will be set to true through set param
10657 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010658
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010659 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010660 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010661
10662 if (k_enable_extended_precision)
10663 adev_verify_devices(adev);
10664
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010665 adev->dsp_bit_width_enforce_mode =
10666 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010667
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010668 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10669 &adev->streams_output_cfg_list,
10670 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010671
Kiran Kandi910e1862013-10-29 13:29:42 -070010672 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010673
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010674 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010675 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010676 trial = atoi(value);
10677 if (period_size_is_plausible_for_low_latency(trial)) {
10678 pcm_config_low_latency.period_size = trial;
10679 pcm_config_low_latency.start_threshold = trial / 4;
10680 pcm_config_low_latency.avail_min = trial / 4;
10681 configured_low_latency_capture_period_size = trial;
10682 }
10683 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010684 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10685 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010686 trial = atoi(value);
10687 if (period_size_is_plausible_for_low_latency(trial)) {
10688 configured_low_latency_capture_period_size = trial;
10689 }
10690 }
10691
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010692 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10693
Eric Laurent4b084132018-10-19 17:33:43 -070010694 adev->camera_orientation = CAMERA_DEFAULT;
10695
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010696 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010697 af_period_multiplier = atoi(value);
10698 if (af_period_multiplier < 0)
10699 af_period_multiplier = 2;
10700 else if (af_period_multiplier > 4)
10701 af_period_multiplier = 4;
10702
10703 ALOGV("new period_multiplier = %d", af_period_multiplier);
10704 }
10705
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010706 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010707
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010708 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010709 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010710 pthread_mutex_unlock(&adev_init_lock);
10711
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010712 if (adev->adm_init)
10713 adev->adm_data = adev->adm_init();
10714
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010715 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010716 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010717
10718 audio_extn_snd_mon_init();
10719 pthread_mutex_lock(&adev->lock);
10720 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10721 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010722 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10723 /*
10724 * if the battery state callback happens before charging can be queried,
10725 * it will be guarded with the adev->lock held in the cb function and so
10726 * the callback value will reflect the latest state
10727 */
10728 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010729 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010730 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010731 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010732 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010733 /* Allocate memory for Device config params */
10734 adev->device_cfg_params = (struct audio_device_config_param*)
10735 calloc(platform_get_max_codec_backend(),
10736 sizeof(struct audio_device_config_param));
10737 if (adev->device_cfg_params == NULL)
10738 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010739
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010740 /*
10741 * Check if new PSPD matrix mixer control is supported. If not
10742 * supported, then set flag so that old mixer ctrl is sent while
10743 * sending pspd coefficients on older kernel version. Query mixer
10744 * control for default pcm id and channel value one.
10745 */
10746 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10747 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10748
10749 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10750 if (!ctl) {
10751 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10752 __func__, mixer_ctl_name);
10753 adev->use_old_pspd_mix_ctrl = true;
10754 }
10755
Eric Laurent994a6932013-07-17 11:51:42 -070010756 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010757 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010758
10759adev_open_err:
10760 free_map(adev->patch_map);
10761 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010762 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010763 pthread_mutex_destroy(&adev->lock);
10764 free(adev);
10765 adev = NULL;
10766 *device = NULL;
10767 pthread_mutex_unlock(&adev_init_lock);
10768 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010769}
10770
10771static struct hw_module_methods_t hal_module_methods = {
10772 .open = adev_open,
10773};
10774
10775struct audio_module HAL_MODULE_INFO_SYM = {
10776 .common = {
10777 .tag = HARDWARE_MODULE_TAG,
10778 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10779 .hal_api_version = HARDWARE_HAL_API_VERSION,
10780 .id = AUDIO_HARDWARE_MODULE_ID,
10781 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010782 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010783 .methods = &hal_module_methods,
10784 },
10785};