blob: ace16c135d9920021d1382d031067629e40fef29 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Aalique Grahame22e49102018-12-18 14:23:57 -0800105#define RECORD_GAIN_MIN 0.0f
106#define RECORD_GAIN_MAX 1.0f
107#define RECORD_VOLUME_CTL_MAX 0x2000
108
109/* treat as unsigned Q1.13 */
110#define APP_TYPE_GAIN_DEFAULT 0x2000
111
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700112#define PROXY_OPEN_RETRY_COUNT 100
113#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800114
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800115#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
116 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
117 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
118#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
119 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800120
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700121#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700122#define DEFAULT_VOIP_BUF_DURATION_MS 20
123#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
124#define DEFAULT_VOIP_SAMP_RATE 48000
125
126#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
127
128struct pcm_config default_pcm_config_voip_copp = {
129 .channels = 1,
130 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
131 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
132 .period_count = 2,
133 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800134 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
135 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700136};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700137
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700138#define MIN_CHANNEL_COUNT 1
139#define DEFAULT_CHANNEL_COUNT 2
140#define MAX_HIFI_CHANNEL_COUNT 8
141
Aalique Grahame22e49102018-12-18 14:23:57 -0800142#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
143#define MAX_CHANNEL_COUNT 1
144#else
145#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
146#define XSTR(x) STR(x)
147#define STR(x) #x
148#endif
149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700150static unsigned int configured_low_latency_capture_period_size =
151 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
152
Haynes Mathew George16081042017-05-31 17:16:49 -0700153#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
154#define MMAP_PERIOD_COUNT_MIN 32
155#define MMAP_PERIOD_COUNT_MAX 512
156#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
157
Aalique Grahame22e49102018-12-18 14:23:57 -0800158/* This constant enables extended precision handling.
159 * TODO The flag is off until more testing is done.
160 */
161static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700162extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800163
Eric Laurentb23d5282013-05-14 15:27:20 -0700164struct pcm_config pcm_config_deep_buffer = {
165 .channels = 2,
166 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
167 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
168 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
171 .stop_threshold = INT_MAX,
172 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
173};
174
175struct pcm_config pcm_config_low_latency = {
176 .channels = 2,
177 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
178 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
179 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
182 .stop_threshold = INT_MAX,
183 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
184};
185
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800186struct pcm_config pcm_config_haptics_audio = {
187 .channels = 1,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
190 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
193 .stop_threshold = INT_MAX,
194 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
195};
196
197struct pcm_config pcm_config_haptics = {
198 .channels = 1,
199 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
200 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
201 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
202 .format = PCM_FORMAT_S16_LE,
203 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
204 .stop_threshold = INT_MAX,
205 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
206};
207
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700208static int af_period_multiplier = 4;
209struct pcm_config pcm_config_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE, //1 ms
213 .period_count = 512, //=> buffer size is 512ms
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Eric Laurentb23d5282013-05-14 15:27:20 -0700222struct pcm_config pcm_config_hdmi_multi = {
223 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
225 .period_size = HDMI_MULTI_PERIOD_SIZE,
226 .period_count = HDMI_MULTI_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .avail_min = 0,
231};
232
Haynes Mathew George16081042017-05-31 17:16:49 -0700233struct pcm_config pcm_config_mmap_playback = {
234 .channels = 2,
235 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
236 .period_size = MMAP_PERIOD_SIZE,
237 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
238 .format = PCM_FORMAT_S16_LE,
239 .start_threshold = MMAP_PERIOD_SIZE*8,
240 .stop_threshold = INT32_MAX,
241 .silence_threshold = 0,
242 .silence_size = 0,
243 .avail_min = MMAP_PERIOD_SIZE, //1 ms
244};
245
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700246struct pcm_config pcm_config_hifi = {
247 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
248 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
249 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
250 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
251 .format = PCM_FORMAT_S24_3LE,
252 .start_threshold = 0,
253 .stop_threshold = INT_MAX,
254 .avail_min = 0,
255};
256
Eric Laurentb23d5282013-05-14 15:27:20 -0700257struct pcm_config pcm_config_audio_capture = {
258 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700259 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261};
262
Haynes Mathew George16081042017-05-31 17:16:49 -0700263struct pcm_config pcm_config_mmap_capture = {
264 .channels = 2,
265 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
266 .period_size = MMAP_PERIOD_SIZE,
267 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
268 .format = PCM_FORMAT_S16_LE,
269 .start_threshold = 0,
270 .stop_threshold = INT_MAX,
271 .silence_threshold = 0,
272 .silence_size = 0,
273 .avail_min = MMAP_PERIOD_SIZE, //1 ms
274};
275
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700276#define AFE_PROXY_CHANNEL_COUNT 2
277#define AFE_PROXY_SAMPLING_RATE 48000
278
279#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
280#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
281
282struct pcm_config pcm_config_afe_proxy_playback = {
283 .channels = AFE_PROXY_CHANNEL_COUNT,
284 .rate = AFE_PROXY_SAMPLING_RATE,
285 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
287 .format = PCM_FORMAT_S16_LE,
288 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
289 .stop_threshold = INT_MAX,
290 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
291};
292
293#define AFE_PROXY_RECORD_PERIOD_SIZE 768
294#define AFE_PROXY_RECORD_PERIOD_COUNT 4
295
Aalique Grahame22e49102018-12-18 14:23:57 -0800296struct pcm_config pcm_config_audio_capture_rt = {
297 .channels = 2,
298 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
299 .period_size = ULL_PERIOD_SIZE,
300 .period_count = 512,
301 .format = PCM_FORMAT_S16_LE,
302 .start_threshold = 0,
303 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
304 .silence_threshold = 0,
305 .silence_size = 0,
306 .avail_min = ULL_PERIOD_SIZE, //1 ms
307};
308
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700309struct pcm_config pcm_config_afe_proxy_record = {
310 .channels = AFE_PROXY_CHANNEL_COUNT,
311 .rate = AFE_PROXY_SAMPLING_RATE,
312 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
313 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
314 .format = PCM_FORMAT_S16_LE,
315 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
316 .stop_threshold = INT_MAX,
317 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
318};
319
Ashish Jainf1eaa582016-05-23 20:54:24 +0530320#define AUDIO_MAX_PCM_FORMATS 7
321
322const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
323 [AUDIO_FORMAT_DEFAULT] = 0,
324 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
325 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
326 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
327 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
329 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
330};
331
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800332const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700333 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
334 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800335 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800336 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700337 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
338 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700339 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700340 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700341 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700349 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
350 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700351 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800352 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700353
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700355 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530356 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
357 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
358 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530359 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
360 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700361 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700362 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700363 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700364 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700365
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800366 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800367 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400368 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
369 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700370
Derek Chenf7092792017-05-23 12:23:53 -0400371 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700372 [USECASE_VOICE2_CALL] = "voice2-call",
373 [USECASE_VOLTE_CALL] = "volte-call",
374 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800375 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800376 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
377 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800378 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700379 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
380 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
381 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800382 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
383 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
384 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
385
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700386 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
387 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700388 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
389 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700390
391 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
392 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800393 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530394 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700395
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530396 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530397 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700399
400 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
401 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530402 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700424};
425
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426static const audio_usecase_t offload_usecases[] = {
427 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437
Varun Balaraje49253e2017-07-06 19:48:56 +0530438static const audio_usecase_t interactive_usecases[] = {
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
447};
448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449#define STRING_TO_ENUM(string) { #string, string }
450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451struct string_to_enum {
452 const char *name;
453 uint32_t value;
454};
455
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476};
477
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700478static const struct string_to_enum formats_name_to_enum_table[] = {
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700485 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800486 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
487 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800489};
490
491//list of all supported sample rates by HDMI specification.
492static const int out_hdmi_sample_rates[] = {
493 32000, 44100, 48000, 88200, 96000, 176400, 192000,
494};
495
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700496static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800497 STRING_TO_ENUM(32000),
498 STRING_TO_ENUM(44100),
499 STRING_TO_ENUM(48000),
500 STRING_TO_ENUM(88200),
501 STRING_TO_ENUM(96000),
502 STRING_TO_ENUM(176400),
503 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800504 STRING_TO_ENUM(352800),
505 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700506};
507
Carter Hsu2e429db2019-05-14 18:50:52 +0800508struct in_effect_list {
509 struct listnode list;
510 effect_handle_t handle;
511};
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700514static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700515static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700516//cache last MBDRC cal step level
517static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530519static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700520static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800521static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530522static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530523
Derek Chen6f293672019-04-01 01:40:24 -0700524static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
525static void in_snd_mon_cb(void * stream, struct str_parms * parms);
526static void out_snd_mon_cb(void * stream, struct str_parms * parms);
527
Zhou Song331c8e52019-08-26 14:16:12 +0800528static int configure_btsco_sample_rate(snd_device_t snd_device);
529
Vatsal Buchac09ae062018-11-14 13:25:08 +0530530#ifdef AUDIO_FEATURE_ENABLED_GCOV
531extern void __gcov_flush();
532static void enable_gcov()
533{
534 __gcov_flush();
535}
536#else
537static void enable_gcov()
538{
539}
540#endif
541
justinweng20fb6d82019-02-21 18:49:00 -0700542static int in_set_microphone_direction(const struct audio_stream_in *stream,
543 audio_microphone_direction_t dir);
544static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
545
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700546static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
547 int flags __unused)
548{
549 int dir = 0;
550 switch (uc_id) {
551 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530552 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700553 dir = 1;
554 case USECASE_AUDIO_PLAYBACK_ULL:
555 break;
556 default:
557 return false;
558 }
559
560 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
561 PCM_PLAYBACK : PCM_CAPTURE);
562 if (adev->adm_is_noirq_avail)
563 return adev->adm_is_noirq_avail(adev->adm_data,
564 adev->snd_card, dev_id, dir);
565 return false;
566}
567
568static void register_out_stream(struct stream_out *out)
569{
570 struct audio_device *adev = out->dev;
571 if (is_offload_usecase(out->usecase) ||
572 !adev->adm_register_output_stream)
573 return;
574
575 // register stream first for backward compatibility
576 adev->adm_register_output_stream(adev->adm_data,
577 out->handle,
578 out->flags);
579
580 if (!adev->adm_set_config)
581 return;
582
583 if (out->realtime)
584 adev->adm_set_config(adev->adm_data,
585 out->handle,
586 out->pcm, &out->config);
587}
588
589static void register_in_stream(struct stream_in *in)
590{
591 struct audio_device *adev = in->dev;
592 if (!adev->adm_register_input_stream)
593 return;
594
595 adev->adm_register_input_stream(adev->adm_data,
596 in->capture_handle,
597 in->flags);
598
599 if (!adev->adm_set_config)
600 return;
601
602 if (in->realtime)
603 adev->adm_set_config(adev->adm_data,
604 in->capture_handle,
605 in->pcm,
606 &in->config);
607}
608
609static void request_out_focus(struct stream_out *out, long ns)
610{
611 struct audio_device *adev = out->dev;
612
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613 if (adev->adm_request_focus_v2)
614 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
615 else if (adev->adm_request_focus)
616 adev->adm_request_focus(adev->adm_data, out->handle);
617}
618
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700619static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700620{
621 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700622 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700623
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624 if (adev->adm_request_focus_v2_1)
625 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
626 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700627 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
628 else if (adev->adm_request_focus)
629 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700630
631 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700632}
633
634static void release_out_focus(struct stream_out *out)
635{
636 struct audio_device *adev = out->dev;
637
638 if (adev->adm_abandon_focus)
639 adev->adm_abandon_focus(adev->adm_data, out->handle);
640}
641
642static void release_in_focus(struct stream_in *in)
643{
644 struct audio_device *adev = in->dev;
645 if (adev->adm_abandon_focus)
646 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
647}
648
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530649static int parse_snd_card_status(struct str_parms *parms, int *card,
650 card_status_t *status)
651{
652 char value[32]={0};
653 char state[32]={0};
654
655 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
656 if (ret < 0)
657 return -1;
658
659 // sscanf should be okay as value is of max length 32.
660 // same as sizeof state.
661 if (sscanf(value, "%d,%s", card, state) < 2)
662 return -1;
663
664 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
665 CARD_STATUS_OFFLINE;
666 return 0;
667}
668
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700669static inline void adjust_frames_for_device_delay(struct stream_out *out,
670 uint32_t *dsp_frames) {
671 // Adjustment accounts for A2dp encoder latency with offload usecases
672 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800673 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700674 unsigned long offset =
675 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
676 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
677 }
678}
679
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700680static inline bool free_entry(void *key __unused,
681 void *value, void *context __unused)
682{
683 free(value);
684 return true;
685}
686
687static inline void free_map(Hashmap *map)
688{
689 if (map) {
690 hashmapForEach(map, free_entry, (void *) NULL);
691 hashmapFree(map);
692 }
693}
694
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800695static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700696 audio_patch_handle_t patch_handle)
697{
698 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
699 return;
700
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 struct audio_patch_info *p_info =
702 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
703 if (p_info) {
704 ALOGV("%s: Remove patch %d", __func__, patch_handle);
705 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
706 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700707 free(p_info);
708 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700709}
710
711static inline int io_streams_map_insert(struct audio_device *adev,
712 struct audio_stream *stream,
713 audio_io_handle_t handle,
714 audio_patch_handle_t patch_handle)
715{
716 struct audio_stream_info *s_info =
717 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
718
719 if (s_info == NULL) {
720 ALOGE("%s: Could not allocate stream info", __func__);
721 return -ENOMEM;
722 }
723 s_info->stream = stream;
724 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700725
726 pthread_mutex_lock(&adev->lock);
727 struct audio_stream_info *stream_info =
728 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700729 if (stream_info != NULL)
730 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800731 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700732 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700733 return 0;
734}
735
736static inline void io_streams_map_remove(struct audio_device *adev,
737 audio_io_handle_t handle)
738{
739 pthread_mutex_lock(&adev->lock);
740 struct audio_stream_info *s_info =
741 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700742 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800743 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700744 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800745 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800747done:
748 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700749 return;
750}
751
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800752static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700753 audio_patch_handle_t handle)
754{
755 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700756 p_info = (struct audio_patch_info *)
757 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700758 return p_info;
759}
760
vivek mehtaa76401a2015-04-24 14:12:15 -0700761__attribute__ ((visibility ("default")))
762bool audio_hw_send_gain_dep_calibration(int level) {
763 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700764 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700765
766 pthread_mutex_lock(&adev_init_lock);
767
768 if (adev != NULL && adev->platform != NULL) {
769 pthread_mutex_lock(&adev->lock);
770 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700771
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530772 // cache level info for any of the use case which
773 // was not started.
774 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700775
vivek mehtaa76401a2015-04-24 14:12:15 -0700776 pthread_mutex_unlock(&adev->lock);
777 } else {
778 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
779 }
780
781 pthread_mutex_unlock(&adev_init_lock);
782
783 return ret_val;
784}
785
Ashish Jain5106d362016-05-11 19:23:33 +0530786static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
787{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800788 bool gapless_enabled = false;
789 const char *mixer_ctl_name = "Compress Gapless Playback";
790 struct mixer_ctl *ctl;
791
792 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700793 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530794
795 /*Disable gapless if its AV playback*/
796 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800797
798 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
799 if (!ctl) {
800 ALOGE("%s: Could not get ctl for mixer cmd - %s",
801 __func__, mixer_ctl_name);
802 return -EINVAL;
803 }
804
805 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
806 ALOGE("%s: Could not set gapless mode %d",
807 __func__, gapless_enabled);
808 return -EINVAL;
809 }
810 return 0;
811}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700812
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700813__attribute__ ((visibility ("default")))
814int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
815 int table_size) {
816 int ret_val = 0;
817 ALOGV("%s: enter ... ", __func__);
818
819 pthread_mutex_lock(&adev_init_lock);
820 if (adev == NULL) {
821 ALOGW("%s: adev is NULL .... ", __func__);
822 goto done;
823 }
824
825 pthread_mutex_lock(&adev->lock);
826 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
827 pthread_mutex_unlock(&adev->lock);
828done:
829 pthread_mutex_unlock(&adev_init_lock);
830 ALOGV("%s: exit ... ", __func__);
831 return ret_val;
832}
833
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800834bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800835{
836 bool ret = false;
837 ALOGV("%s: enter ...", __func__);
838
839 pthread_mutex_lock(&adev_init_lock);
840
841 if (adev != NULL && adev->platform != NULL) {
842 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800843 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800844 pthread_mutex_unlock(&adev->lock);
845 }
846
847 pthread_mutex_unlock(&adev_init_lock);
848
849 ALOGV("%s: exit with ret %d", __func__, ret);
850 return ret;
851}
Aalique Grahame22e49102018-12-18 14:23:57 -0800852
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700853static bool is_supported_format(audio_format_t format)
854{
Eric Laurent86e17132013-09-12 17:49:30 -0700855 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530856 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530857 format == AUDIO_FORMAT_AAC_LC ||
858 format == AUDIO_FORMAT_AAC_HE_V1 ||
859 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530860 format == AUDIO_FORMAT_AAC_ADTS_LC ||
861 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
862 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530863 format == AUDIO_FORMAT_AAC_LATM_LC ||
864 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
865 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530866 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
867 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530868 format == AUDIO_FORMAT_PCM_FLOAT ||
869 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700870 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530871 format == AUDIO_FORMAT_AC3 ||
872 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700873 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530874 format == AUDIO_FORMAT_DTS ||
875 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800876 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530877 format == AUDIO_FORMAT_ALAC ||
878 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530879 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530880 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800881 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530882 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700883 format == AUDIO_FORMAT_APTX ||
884 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800885 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700886
887 return false;
888}
889
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700890static inline bool is_mmap_usecase(audio_usecase_t uc_id)
891{
892 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800893 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700894 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
895}
896
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700897static inline bool is_valid_volume(float left, float right)
898{
899 return ((left >= 0.0f && right >= 0.0f) ? true : false);
900}
901
Avinash Vaish71a8b972014-07-24 15:36:33 +0530902static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
903 struct audio_usecase *uc_info)
904{
905 struct listnode *node;
906 struct audio_usecase *usecase;
907
908 if (uc_info == NULL)
909 return -EINVAL;
910
911 /* Re-route all voice usecases on the shared backend other than the
912 specified usecase to new snd devices */
913 list_for_each(node, &adev->usecase_list) {
914 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800915 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530916 enable_audio_route(adev, usecase);
917 }
918 return 0;
919}
920
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530921static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530922{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530923 ALOGV("%s", __func__);
924 audio_route_apply_and_update_path(adev->audio_route,
925 "asrc-mode");
926 adev->asrc_mode_enabled = true;
927}
928
929static void disable_asrc_mode(struct audio_device *adev)
930{
931 ALOGV("%s", __func__);
932 audio_route_reset_and_update_path(adev->audio_route,
933 "asrc-mode");
934 adev->asrc_mode_enabled = false;
935}
936
937/*
938 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
939 * 44.1 or Native DSD backends are enabled for any of current use case.
940 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
941 * - Disable current mix path use case(Headphone backend) and re-enable it with
942 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
943 * e.g. Naitve DSD or Headphone 44.1 -> + 48
944 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530945static void check_and_set_asrc_mode(struct audio_device *adev,
946 struct audio_usecase *uc_info,
947 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530948{
949 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530950 int i, num_new_devices = 0;
951 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
952 /*
953 *Split snd device for new combo use case
954 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
955 */
956 if (platform_split_snd_device(adev->platform,
957 snd_device,
958 &num_new_devices,
959 split_new_snd_devices) == 0) {
960 for (i = 0; i < num_new_devices; i++)
961 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
962 } else {
963 int new_backend_idx = platform_get_backend_index(snd_device);
964 if (((new_backend_idx == HEADPHONE_BACKEND) ||
965 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
966 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
967 !adev->asrc_mode_enabled) {
968 struct listnode *node = NULL;
969 struct audio_usecase *uc = NULL;
970 struct stream_out *curr_out = NULL;
971 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
972 int i, num_devices, ret = 0;
973 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530974
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530975 list_for_each(node, &adev->usecase_list) {
976 uc = node_to_item(node, struct audio_usecase, list);
977 curr_out = (struct stream_out*) uc->stream.out;
978 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
979 /*
980 *Split snd device for existing combo use case
981 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
982 */
983 ret = platform_split_snd_device(adev->platform,
984 uc->out_snd_device,
985 &num_devices,
986 split_snd_devices);
987 if (ret < 0 || num_devices == 0) {
988 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
989 split_snd_devices[0] = uc->out_snd_device;
990 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800991 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530992 for (i = 0; i < num_devices; i++) {
993 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
994 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
995 if((new_backend_idx == HEADPHONE_BACKEND) &&
996 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
997 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700998 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530999 __func__);
1000 enable_asrc_mode(adev);
1001 break;
1002 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1003 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1004 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001005 ALOGV("%s: 48K stream detected, disabling and enabling it \
1006 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301007 disable_audio_route(adev, uc);
1008 disable_snd_device(adev, uc->out_snd_device);
1009 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1010 if (new_backend_idx == DSD_NATIVE_BACKEND)
1011 audio_route_apply_and_update_path(adev->audio_route,
1012 "hph-true-highquality-mode");
1013 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1014 (curr_out->bit_width >= 24))
1015 audio_route_apply_and_update_path(adev->audio_route,
1016 "hph-highquality-mode");
1017 enable_asrc_mode(adev);
1018 enable_snd_device(adev, uc->out_snd_device);
1019 enable_audio_route(adev, uc);
1020 break;
1021 }
1022 }
1023 // reset split devices count
1024 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001025 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301026 if (adev->asrc_mode_enabled)
1027 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301028 }
1029 }
1030 }
1031}
1032
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001033static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1034 struct audio_effect_config effect_config,
1035 unsigned int param_value)
1036{
1037 char mixer_ctl_name[] = "Audio Effect";
1038 struct mixer_ctl *ctl;
1039 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001040 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001042 if (in == NULL) {
1043 ALOGE("%s: active input stream is NULL", __func__);
1044 return -EINVAL;
1045 }
1046
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001047 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1048 if (!ctl) {
1049 ALOGE("%s: Could not get mixer ctl - %s",
1050 __func__, mixer_ctl_name);
1051 return -EINVAL;
1052 }
1053
1054 set_values[0] = 1; //0:Rx 1:Tx
1055 set_values[1] = in->app_type_cfg.app_type;
1056 set_values[2] = (long)effect_config.module_id;
1057 set_values[3] = (long)effect_config.instance_id;
1058 set_values[4] = (long)effect_config.param_id;
1059 set_values[5] = param_value;
1060
1061 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1062
1063 return 0;
1064
1065}
1066
1067static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1068 int effect_type, unsigned int *param_value)
1069{
1070 int ret = 0;
1071 struct audio_effect_config other_effect_config;
1072 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001073 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001075 if (in == NULL) {
1076 ALOGE("%s: active input stream is NULL", __func__);
1077 return -EINVAL;
1078 }
1079
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001080 usecase = get_usecase_from_list(adev, in->usecase);
1081 if (!usecase)
1082 return -EINVAL;
1083
1084 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1085 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1086 if (ret < 0) {
1087 ALOGE("%s Failed to get effect params %d", __func__, ret);
1088 return ret;
1089 }
1090
1091 if (module_id == other_effect_config.module_id) {
1092 //Same module id for AEC/NS. Values need to be combined
1093 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1094 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1095 *param_value |= other_effect_config.param_value;
1096 }
1097 }
1098
1099 return ret;
1100}
1101
1102static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301103{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001104 struct audio_effect_config effect_config;
1105 struct audio_usecase *usecase = NULL;
1106 int ret = 0;
1107 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001108 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001110 if(!voice_extn_is_dynamic_ecns_enabled())
1111 return ENOSYS;
1112
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001113 if (!in) {
1114 ALOGE("%s: Invalid input stream", __func__);
1115 return -EINVAL;
1116 }
1117
1118 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1119
1120 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001121 if (usecase == NULL) {
1122 ALOGE("%s: Could not find the usecase (%d) in the list",
1123 __func__, in->usecase);
1124 return -EINVAL;
1125 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001126
1127 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1128 if (ret < 0) {
1129 ALOGE("%s Failed to get module id %d", __func__, ret);
1130 return ret;
1131 }
1132 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1133 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1134
1135 if(enable)
1136 param_value = effect_config.param_value;
1137
1138 /*Special handling for AEC & NS effects Param values need to be
1139 updated if module ids are same*/
1140
1141 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1142 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1143 if (ret < 0)
1144 return ret;
1145 }
1146
1147 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1148
1149 return ret;
1150}
1151
1152static void check_and_enable_effect(struct audio_device *adev)
1153{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001154 if(!voice_extn_is_dynamic_ecns_enabled())
1155 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156
Eric Laurent637e2d42018-11-15 12:24:31 -08001157 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158
Eric Laurent637e2d42018-11-15 12:24:31 -08001159 if (in != NULL && !in->standby) {
1160 if (in->enable_aec)
1161 enable_disable_effect(adev, EFFECT_AEC, true);
1162
1163 if (in->enable_ns &&
1164 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1165 enable_disable_effect(adev, EFFECT_NS, true);
1166 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001167 }
1168}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001169
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001170int pcm_ioctl(struct pcm *pcm, int request, ...)
1171{
1172 va_list ap;
1173 void * arg;
1174 int pcm_fd = *(int*)pcm;
1175
1176 va_start(ap, request);
1177 arg = va_arg(ap, void *);
1178 va_end(ap);
1179
1180 return ioctl(pcm_fd, request, arg);
1181}
1182
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001183int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001184 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001187 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301188 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301189 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001190 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301191 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001192
1193 if (usecase == NULL)
1194 return -EINVAL;
1195
1196 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1197
Carter Hsu2e429db2019-05-14 18:50:52 +08001198 if (usecase->type == PCM_CAPTURE) {
1199 struct stream_in *in = usecase->stream.in;
1200 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001202
1203 if (in) {
1204 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 list_init(&out_devices);
1206 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 struct listnode *node;
1208 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1209 USECASE_AUDIO_PLAYBACK_VOIP);
1210 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001211 assign_devices(&out_devices,
1212 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001213 } else if (adev->primary_output &&
1214 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001215 assign_devices(&out_devices,
1216 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 } else {
1218 list_for_each(node, &adev->usecase_list) {
1219 uinfo = node_to_item(node, struct audio_usecase, list);
1220 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001221 assign_devices(&out_devices,
1222 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001223 break;
1224 }
1225 }
1226 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001227
1228 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 in->ec_opened = true;
1230 }
1231 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001232 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1233 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1234 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001235 snd_device = usecase->in_snd_device;
1236 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001238 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001239
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001240#ifdef DS1_DOLBY_DAP_ENABLED
1241 audio_extn_dolby_set_dmid(adev);
1242 audio_extn_dolby_set_endpoint(adev);
1243#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001244 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001245 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301246 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001247 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001248 if (audio_extn_is_maxx_audio_enabled())
1249 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301250 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301251 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1252 out = usecase->stream.out;
1253 if (out && out->compr)
1254 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1255 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301256
1257 if (usecase->type == PCM_CAPTURE) {
1258 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001259 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301260 ALOGD("%s: set custom mtmx params v1", __func__);
1261 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1262 }
1263 } else {
1264 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1265 }
Manish Dewangan58229382017-02-02 15:48:41 +05301266
Andy Hung756ecc12018-10-19 17:47:12 -07001267 // we shouldn't truncate mixer_path
1268 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1269 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1270 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001271 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001272 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301273 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1274 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1275 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1276 if (parms) {
1277 audio_extn_fm_set_parameters(adev, parms);
1278 str_parms_destroy(parms);
1279 }
1280 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 ALOGV("%s: exit", __func__);
1282 return 0;
1283}
1284
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001285int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001286 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001289 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301290 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001291
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301292 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001293 return -EINVAL;
1294
1295 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301296 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 snd_device = usecase->in_snd_device;
1298 else
1299 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001300
1301 /* disable island and power mode on supported device for voice call */
1302 if (usecase->type == VOICE_CALL) {
1303 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1304 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1305 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1306 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1307 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1308 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1309 ALOGD("%s: disable island cfg and power mode in voice tx path",
1310 __func__);
1311 }
1312 }
1313 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1314 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1315 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1316 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1317 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1318 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1319 ALOGD("%s: disable island cfg and power mode in voice rx path",
1320 __func__);
1321 }
1322 }
1323 }
1324
Andy Hung756ecc12018-10-19 17:47:12 -07001325 // we shouldn't truncate mixer_path
1326 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1327 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1328 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001329 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001330 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001331 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001332 if (usecase->type == PCM_CAPTURE) {
1333 struct stream_in *in = usecase->stream.in;
1334 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001335 struct listnode out_devices;
1336 list_init(&out_devices);
1337 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001338 in->ec_opened = false;
1339 }
1340 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001341 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301342 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301343
1344 if (usecase->type == PCM_CAPTURE) {
1345 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001346 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301347 ALOGD("%s: reset custom mtmx params v1", __func__);
1348 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1349 }
1350 } else {
1351 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1352 }
1353
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001354 if ((usecase->type == PCM_PLAYBACK) &&
1355 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301356 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358 ALOGV("%s: exit", __func__);
1359 return 0;
1360}
1361
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001362int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001363 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301365 int i, num_devices = 0;
1366 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001367 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1368
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001369 if (snd_device < SND_DEVICE_MIN ||
1370 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001371 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001372 return -EINVAL;
1373 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001375 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001376 ALOGE("%s: Invalid sound device returned", __func__);
1377 return -EINVAL;
1378 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001379
1380 adev->snd_dev_ref_cnt[snd_device]++;
1381
1382 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1383 (platform_split_snd_device(adev->platform,
1384 snd_device,
1385 &num_devices,
1386 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001387 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001388 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001389 /* Set backend config for A2DP to ensure slimbus configuration
1390 is correct if A2DP is already active and backend is closed
1391 and re-opened */
1392 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1393 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394 return 0;
1395 }
1396
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001397 if (audio_extn_spkr_prot_is_enabled())
1398 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001399
Aalique Grahame22e49102018-12-18 14:23:57 -08001400 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1401
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001402 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1403 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001404 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1405 goto err;
1406 }
1407 audio_extn_dev_arbi_acquire(snd_device);
1408 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001409 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001410 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001411 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001412 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001413 } else if (platform_split_snd_device(adev->platform,
1414 snd_device,
1415 &num_devices,
1416 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301417 for (i = 0; i < num_devices; i++) {
1418 enable_snd_device(adev, new_snd_devices[i]);
1419 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001420 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001421 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001422 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301423
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001424 /* enable island and power mode on supported device */
1425 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1426 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1427 platform_set_island_cfg_on_device(adev, snd_device, true);
1428 platform_set_power_mode_on_device(adev, snd_device, true);
1429 ALOGD("%s: enable island cfg and power mode on: %s",
1430 __func__, device_name);
1431 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301432
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301433 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1434 if (audio_extn_a2dp_start_playback() < 0) {
1435 ALOGE(" fail to configure A2dp Source control path ");
1436 goto err;
1437 } else {
1438 adev->a2dp_started = true;
1439 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001440 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001441
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001442 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1443 (audio_extn_a2dp_start_capture() < 0)) {
1444 ALOGE(" fail to configure A2dp Sink control path ");
1445 goto err;
1446 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301447
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001448 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1449 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1450 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1451 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1452 ALOGE(" fail to configure sco control path ");
1453 goto err;
1454 }
Zhou Song12c29502019-03-16 10:37:18 +08001455 }
1456
Zhou Song331c8e52019-08-26 14:16:12 +08001457 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001458 /* due to the possibility of calibration overwrite between listen
1459 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001460 audio_extn_sound_trigger_update_device_status(snd_device,
1461 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301462 audio_extn_listen_update_device_status(snd_device,
1463 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001464 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001465 audio_extn_sound_trigger_update_device_status(snd_device,
1466 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301467 audio_extn_listen_update_device_status(snd_device,
1468 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001469 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001470 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001471 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001472 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301473
1474 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1475 !adev->native_playback_enabled &&
1476 audio_is_true_native_stream_active(adev)) {
1477 ALOGD("%s: %d: napb: enabling native mode in hardware",
1478 __func__, __LINE__);
1479 audio_route_apply_and_update_path(adev->audio_route,
1480 "true-native-mode");
1481 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301482 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301483 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1484 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001485 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001486 ALOGD("%s: init ec ref loopback", __func__);
1487 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1488 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001491err:
1492 adev->snd_dev_ref_cnt[snd_device]--;
1493 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494}
1495
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001496int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001497 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301499 int i, num_devices = 0;
1500 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001501 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1502
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001503 if (snd_device < SND_DEVICE_MIN ||
1504 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001505 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001506 return -EINVAL;
1507 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001508
1509 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1510 ALOGE("%s: Invalid sound device returned", __func__);
1511 return -EINVAL;
1512 }
1513
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001514 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1515 ALOGE("%s: device ref cnt is already 0", __func__);
1516 return -EINVAL;
1517 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001518
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001520
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001521
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001522 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001523 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301524
Aalique Grahame22e49102018-12-18 14:23:57 -08001525 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1526
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001527 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1528 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001529 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001530
1531 // when speaker device is disabled, reset swap.
1532 // will be renabled on usecase start
1533 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001534 } else if (platform_split_snd_device(adev->platform,
1535 snd_device,
1536 &num_devices,
1537 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301538 for (i = 0; i < num_devices; i++) {
1539 disable_snd_device(adev, new_snd_devices[i]);
1540 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001541 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001542 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001543 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001544 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001545
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301546 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301547 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301548 adev->a2dp_started = false;
1549 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001550 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001551 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001552 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301553 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001554 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301555 adev->native_playback_enabled) {
1556 ALOGD("%s: %d: napb: disabling native mode in hardware",
1557 __func__, __LINE__);
1558 audio_route_reset_and_update_path(adev->audio_route,
1559 "true-native-mode");
1560 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001561 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301562 adev->asrc_mode_enabled) {
1563 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301564 disable_asrc_mode(adev);
1565 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001566 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301567 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001568 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001569 ALOGD("%s: deinit ec ref loopback", __func__);
1570 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1571 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001572
1573 audio_extn_utils_release_snd_device(snd_device);
1574 } else {
1575 if (platform_split_snd_device(adev->platform,
1576 snd_device,
1577 &num_devices,
1578 new_snd_devices) == 0) {
1579 for (i = 0; i < num_devices; i++) {
1580 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1581 }
1582 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001583 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 return 0;
1586}
1587
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001588/*
1589 legend:
1590 uc - existing usecase
1591 new_uc - new usecase
1592 d1, d11, d2 - SND_DEVICE enums
1593 a1, a2 - corresponding ANDROID device enums
1594 B1, B2 - backend strings
1595
1596case 1
1597 uc->dev d1 (a1) B1
1598 new_uc->dev d1 (a1), d2 (a2) B1, B2
1599
1600 resolution: disable and enable uc->dev on d1
1601
1602case 2
1603 uc->dev d1 (a1) B1
1604 new_uc->dev d11 (a1) B1
1605
1606 resolution: need to switch uc since d1 and d11 are related
1607 (e.g. speaker and voice-speaker)
1608 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1609
1610case 3
1611 uc->dev d1 (a1) B1
1612 new_uc->dev d2 (a2) B2
1613
1614 resolution: no need to switch uc
1615
1616case 4
1617 uc->dev d1 (a1) B1
1618 new_uc->dev d2 (a2) B1
1619
1620 resolution: disable enable uc-dev on d2 since backends match
1621 we cannot enable two streams on two different devices if they
1622 share the same backend. e.g. if offload is on speaker device using
1623 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1624 using the same backend, offload must also be switched to voice-handset.
1625
1626case 5
1627 uc->dev d1 (a1) B1
1628 new_uc->dev d1 (a1), d2 (a2) B1
1629
1630 resolution: disable enable uc-dev on d2 since backends match
1631 we cannot enable two streams on two different devices if they
1632 share the same backend.
1633
1634case 6
1635 uc->dev d1 (a1) B1
1636 new_uc->dev d2 (a1) B2
1637
1638 resolution: no need to switch
1639
1640case 7
1641 uc->dev d1 (a1), d2 (a2) B1, B2
1642 new_uc->dev d1 (a1) B1
1643
1644 resolution: no need to switch
1645
Zhou Song4ba65882018-07-09 14:48:07 +08001646case 8
1647 uc->dev d1 (a1) B1
1648 new_uc->dev d11 (a1), d2 (a2) B1, B2
1649 resolution: compared to case 1, for this case, d1 and d11 are related
1650 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301651
1652case 9
1653 uc->dev d1 (a1), d2(a2) B1 B2
1654 new_uc->dev d1 (a1), d22 (a2) B1, B2
1655 resolution: disable enable uc-dev on d2 since backends match
1656 we cannot enable two streams on two different devices if they
1657 share the same backend. This is special case for combo use case
1658 with a2dp and sco devices which uses same backend.
1659 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001660*/
1661static snd_device_t derive_playback_snd_device(void * platform,
1662 struct audio_usecase *uc,
1663 struct audio_usecase *new_uc,
1664 snd_device_t new_snd_device)
1665{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001666 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001667
1668 snd_device_t d1 = uc->out_snd_device;
1669 snd_device_t d2 = new_snd_device;
1670
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001671 list_init(&a1);
1672 list_init(&a2);
1673
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301674 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301675 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001676 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1677 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301678 break;
1679 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001680 assign_devices(&a1, &uc->stream.out->device_list);
1681 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301682 break;
1683 }
1684
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001685 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001686 if (!compare_devices(&a1, &a2) &&
1687 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001688 snd_device_t d3[2];
1689 int num_devices = 0;
1690 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001691 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001692 &num_devices,
1693 d3);
1694 if (ret < 0) {
1695 if (ret != -ENOSYS) {
1696 ALOGW("%s failed to split snd_device %d",
1697 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001698 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001699 }
1700 goto end;
1701 }
1702
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001703 if (platform_check_backends_match(d3[0], d3[1])) {
1704 return d2; // case 5
1705 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301706 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1707 platform_check_backends_match(d1, d2))
1708 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001709 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301710 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001711 // check if d1 is related to any of d3's
1712 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001713 return d1; // case 1
1714 else
1715 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001716 }
1717 } else {
1718 if (platform_check_backends_match(d1, d2)) {
1719 return d2; // case 2, 4
1720 } else {
1721 return d1; // case 6, 3
1722 }
1723 }
1724
1725end:
1726 return d2; // return whatever was calculated before.
1727}
1728
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001729static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301730 struct audio_usecase *uc_info,
1731 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001732{
1733 struct listnode *node;
1734 struct audio_usecase *usecase;
1735 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301736 snd_device_t uc_derive_snd_device;
1737 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001738 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1739 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001740 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301741 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001742 /*
1743 * This function is to make sure that all the usecases that are active on
1744 * the hardware codec backend are always routed to any one device that is
1745 * handled by the hardware codec.
1746 * For example, if low-latency and deep-buffer usecases are currently active
1747 * on speaker and out_set_parameters(headset) is received on low-latency
1748 * output, then we have to make sure deep-buffer is also switched to headset,
1749 * because of the limitation that both the devices cannot be enabled
1750 * at the same time as they share the same backend.
1751 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001752 /*
1753 * This call is to check if we need to force routing for a particular stream
1754 * If there is a backend configuration change for the device when a
1755 * new stream starts, then ADM needs to be closed and re-opened with the new
1756 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001757 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001758 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001759 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1760 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301761 /* For a2dp device reconfigure all active sessions
1762 * with new AFE encoder format based on a2dp state
1763 */
1764 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301765 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1766 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301767 audio_extn_a2dp_is_force_device_switch()) {
1768 force_routing = true;
1769 force_restart_session = true;
1770 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001771
1772 /*
1773 * Island cfg and power mode config needs to set before AFE port start.
1774 * Set force routing in case of voice device was enable before.
1775 */
1776 if (uc_info->type == VOICE_CALL &&
1777 voice_extn_is_voice_power_mode_supported() &&
1778 platform_check_and_update_island_power_status(adev->platform,
1779 uc_info,
1780 snd_device)) {
1781 force_routing = true;
1782 ALOGD("%s:becf: force routing %d for power mode supported device",
1783 __func__, force_routing);
1784 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301785 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1786
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001787 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001788 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001789 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001790 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1791 switch_device[i] = false;
1792
1793 list_for_each(node, &adev->usecase_list) {
1794 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001795
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301796 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1797 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301798 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301799 platform_get_snd_device_name(usecase->out_snd_device),
1800 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301801 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1802 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301803 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1804 usecase, uc_info, snd_device);
1805 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001806 (is_codec_backend_out_device_type(&usecase->device_list) ||
1807 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1808 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1809 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1810 is_a2dp_out_device_type(&usecase->device_list) ||
1811 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301812 ((force_restart_session) ||
1813 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301814 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1815 __func__, use_case_table[usecase->id],
1816 platform_get_snd_device_name(usecase->out_snd_device));
1817 disable_audio_route(adev, usecase);
1818 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301819 /* Enable existing usecase on derived playback device */
1820 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301821 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 }
1824 }
1825
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301826 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1827 num_uc_to_switch);
1828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001830 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301832 /* Make sure the previous devices to be disabled first and then enable the
1833 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834 list_for_each(node, &adev->usecase_list) {
1835 usecase = node_to_item(node, struct audio_usecase, list);
1836 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001837 /* Check if output sound device to be switched can be split and if any
1838 of the split devices match with derived sound device */
1839 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1840 &num_devices, split_snd_devices) == 0) {
1841 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1842 for (i = 0; i < num_devices; i++) {
1843 /* Disable devices that do not match with derived sound device */
1844 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1845 disable_snd_device(adev, split_snd_devices[i]);
1846 }
1847 } else {
1848 disable_snd_device(adev, usecase->out_snd_device);
1849 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001850 }
1851 }
1852
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001853 list_for_each(node, &adev->usecase_list) {
1854 usecase = node_to_item(node, struct audio_usecase, list);
1855 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001856 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1857 &num_devices, split_snd_devices) == 0) {
1858 /* Enable derived sound device only if it does not match with
1859 one of the split sound devices. This is because the matching
1860 sound device was not disabled */
1861 bool should_enable = true;
1862 for (i = 0; i < num_devices; i++) {
1863 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1864 should_enable = false;
1865 break;
1866 }
1867 }
1868 if (should_enable)
1869 enable_snd_device(adev, derive_snd_device[usecase->id]);
1870 } else {
1871 enable_snd_device(adev, derive_snd_device[usecase->id]);
1872 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001873 }
1874 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 /* Re-route all the usecases on the shared backend other than the
1877 specified usecase to new snd devices */
1878 list_for_each(node, &adev->usecase_list) {
1879 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301880 /* Update the out_snd_device only before enabling the audio route */
1881 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301882 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301883 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301884 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301885 use_case_table[usecase->id],
1886 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001887 /* Update voc calibration before enabling VoIP route */
1888 if (usecase->type == VOIP_CALL)
1889 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001890 usecase->out_snd_device,
1891 platform_get_input_snd_device(
1892 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301893 &uc_info->device_list,
1894 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301895 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301896 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001897 out_set_voip_volume(&usecase->stream.out->stream,
1898 usecase->stream.out->volume_l,
1899 usecase->stream.out->volume_r);
1900 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902 }
1903 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 }
1905}
1906
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301907static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 struct audio_usecase *uc_info,
1909 snd_device_t snd_device)
1910{
1911 struct listnode *node;
1912 struct audio_usecase *usecase;
1913 bool switch_device[AUDIO_USECASE_MAX];
1914 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001915 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001916 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001917
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301918 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1919 snd_device);
1920 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301921
1922 /*
1923 * Make sure out devices is checked against out codec backend device and
1924 * also in devices against in codec backend. Checking out device against in
1925 * codec backend or vice versa causes issues.
1926 */
1927 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001928 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001929
1930 /*
1931 * Island cfg and power mode config needs to set before AFE port start.
1932 * Set force routing in case of voice device was enable before.
1933 */
1934
1935 if (uc_info->type == VOICE_CALL &&
1936 voice_extn_is_voice_power_mode_supported() &&
1937 platform_check_and_update_island_power_status(adev->platform,
1938 uc_info,
1939 snd_device)) {
1940 force_routing = true;
1941 ALOGD("%s:becf: force routing %d for power mode supported device",
1942 __func__, force_routing);
1943 }
1944
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001945 /*
1946 * This function is to make sure that all the active capture usecases
1947 * are always routed to the same input sound device.
1948 * For example, if audio-record and voice-call usecases are currently
1949 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1950 * is received for voice call then we have to make sure that audio-record
1951 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1952 * because of the limitation that two devices cannot be enabled
1953 * at the same time if they share the same backend.
1954 */
1955 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1956 switch_device[i] = false;
1957
1958 list_for_each(node, &adev->usecase_list) {
1959 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301960 /*
1961 * TODO: Enhance below condition to handle BT sco/USB multi recording
1962 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301963
1964 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1965 (usecase->in_snd_device != snd_device || force_routing));
1966 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1967 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1968 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001969 ((backend_check_cond &&
1970 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001971 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001972 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001973 is_single_device_type_equal(&usecase->device_list,
1974 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001975 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001976 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001977 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301978 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001979 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001980 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001981 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001982 switch_device[usecase->id] = true;
1983 num_uc_to_switch++;
1984 }
1985 }
1986
1987 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001988 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001989
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301990 /* Make sure the previous devices to be disabled first and then enable the
1991 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001992 list_for_each(node, &adev->usecase_list) {
1993 usecase = node_to_item(node, struct audio_usecase, list);
1994 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001995 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001996 }
1997 }
1998
1999 list_for_each(node, &adev->usecase_list) {
2000 usecase = node_to_item(node, struct audio_usecase, list);
2001 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002002 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002003 }
2004 }
2005
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002006 /* Re-route all the usecases on the shared backend other than the
2007 specified usecase to new snd devices */
2008 list_for_each(node, &adev->usecase_list) {
2009 usecase = node_to_item(node, struct audio_usecase, list);
2010 /* Update the in_snd_device only before enabling the audio route */
2011 if (switch_device[usecase->id] ) {
2012 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08002013 if (usecase->type != VOICE_CALL) {
2014 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302015 if (usecase->type == VOIP_CALL) {
2016 snd_device_t voip_snd_device;
2017 voip_snd_device = platform_get_output_snd_device(adev->platform,
2018 uc_info->stream.out,
2019 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002020 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302021 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002022 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302023 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302024 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002025 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002026 }
2027 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002028 }
2029}
2030
Mingming Yin3a941d42016-02-17 18:08:05 -08002031static void reset_hdmi_sink_caps(struct stream_out *out) {
2032 int i = 0;
2033
2034 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2035 out->supported_channel_masks[i] = 0;
2036 }
2037 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2038 out->supported_formats[i] = 0;
2039 }
2040 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2041 out->supported_sample_rates[i] = 0;
2042 }
2043}
2044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002046static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047{
Mingming Yin3a941d42016-02-17 18:08:05 -08002048 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002049 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2050 out->extconn.cs.controller,
2051 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Mingming Yin3a941d42016-02-17 18:08:05 -08002053 reset_hdmi_sink_caps(out);
2054
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002055 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002056 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002057 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002058 out->extconn.cs.stream);
2059 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002060 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002061 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002062 }
2063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002066 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002067 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002068 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2069 case 6:
2070 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2071 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2072 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2073 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2074 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2075 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 break;
2077 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002078 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002079 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 break;
2081 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002082
2083 // check channel format caps
2084 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002085 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2086 out->extconn.cs.controller,
2087 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002088 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2089 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2090 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2091 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2092 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2093 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2094 }
2095
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002096 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2097 out->extconn.cs.controller,
2098 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002099 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2100 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2101 }
2102
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002103 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2104 out->extconn.cs.controller,
2105 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002106 ALOGV(":%s HDMI supports DTS format", __func__);
2107 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2108 }
2109
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002110 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2111 out->extconn.cs.controller,
2112 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002113 ALOGV(":%s HDMI supports DTS HD format", __func__);
2114 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2115 }
2116
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002117 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2118 out->extconn.cs.controller,
2119 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002120 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2121 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2122 }
2123
Mingming Yin3a941d42016-02-17 18:08:05 -08002124
2125 // check sample rate caps
2126 i = 0;
2127 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002128 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2129 out->extconn.cs.controller,
2130 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002131 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2132 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2133 }
2134 }
2135
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002136 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137}
2138
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002139static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2140 uint32_t *supported_sample_rates __unused,
2141 uint32_t max_rates __unused)
2142{
2143 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2144 supported_sample_rates,
2145 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302146 ssize_t i = 0;
2147
2148 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002149 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2150 supported_sample_rates[i]);
2151 }
2152 return count;
2153}
2154
2155static inline int read_usb_sup_channel_masks(bool is_playback,
2156 audio_channel_mask_t *supported_channel_masks,
2157 uint32_t max_masks)
2158{
2159 int channels = audio_extn_usb_get_max_channels(is_playback);
2160 int channel_count;
2161 uint32_t num_masks = 0;
2162 if (channels > MAX_HIFI_CHANNEL_COUNT)
2163 channels = MAX_HIFI_CHANNEL_COUNT;
2164
2165 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002166 // start from 2 channels as framework currently doesn't support mono.
2167 if (channels >= FCC_2) {
2168 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2169 }
2170 for (channel_count = FCC_2;
2171 channel_count <= channels && num_masks < max_masks;
2172 ++channel_count) {
2173 supported_channel_masks[num_masks++] =
2174 audio_channel_mask_for_index_assignment_from_count(channel_count);
2175 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002176 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002177 // For capture we report all supported channel masks from 1 channel up.
2178 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002179 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2180 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002181 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2182 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2183 if (channel_count <= FCC_2) {
2184 mask = audio_channel_in_mask_from_count(channel_count);
2185 supported_channel_masks[num_masks++] = mask;
2186 }
2187 const audio_channel_mask_t index_mask =
2188 audio_channel_mask_for_index_assignment_from_count(channel_count);
2189 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2190 supported_channel_masks[num_masks++] = index_mask;
2191 }
2192 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002193 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302194
vincenttewf51c94e2019-05-07 10:28:53 +08002195 for (size_t i = 0; i < num_masks; ++i) {
2196 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2197 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302198 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002199 return num_masks;
2200}
2201
2202static inline int read_usb_sup_formats(bool is_playback __unused,
2203 audio_format_t *supported_formats,
2204 uint32_t max_formats __unused)
2205{
2206 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2207 switch (bitwidth) {
2208 case 24:
2209 // XXX : usb.c returns 24 for s24 and s24_le?
2210 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2211 break;
2212 case 32:
2213 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2214 break;
2215 case 16:
2216 default :
2217 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2218 break;
2219 }
2220 ALOGV("%s: %s supported format %d", __func__,
2221 is_playback ? "P" : "C", bitwidth);
2222 return 1;
2223}
2224
2225static inline int read_usb_sup_params_and_compare(bool is_playback,
2226 audio_format_t *format,
2227 audio_format_t *supported_formats,
2228 uint32_t max_formats,
2229 audio_channel_mask_t *mask,
2230 audio_channel_mask_t *supported_channel_masks,
2231 uint32_t max_masks,
2232 uint32_t *rate,
2233 uint32_t *supported_sample_rates,
2234 uint32_t max_rates) {
2235 int ret = 0;
2236 int num_formats;
2237 int num_masks;
2238 int num_rates;
2239 int i;
2240
2241 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2242 max_formats);
2243 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2244 max_masks);
2245
2246 num_rates = read_usb_sup_sample_rates(is_playback,
2247 supported_sample_rates, max_rates);
2248
2249#define LUT(table, len, what, dflt) \
2250 for (i=0; i<len && (table[i] != what); i++); \
2251 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2252
2253 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2254 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2255 LUT(supported_sample_rates, num_rates, *rate, 0);
2256
2257#undef LUT
2258 return ret < 0 ? -EINVAL : 0; // HACK TBD
2259}
2260
Alexy Josephb1379942016-01-29 15:49:38 -08002261audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002262 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002263{
2264 struct audio_usecase *usecase;
2265 struct listnode *node;
2266
2267 list_for_each(node, &adev->usecase_list) {
2268 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002269 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002270 ALOGV("%s: usecase id %d", __func__, usecase->id);
2271 return usecase->id;
2272 }
2273 }
2274 return USECASE_INVALID;
2275}
2276
Alexy Josephb1379942016-01-29 15:49:38 -08002277struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002278 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002279{
2280 struct audio_usecase *usecase;
2281 struct listnode *node;
2282
2283 list_for_each(node, &adev->usecase_list) {
2284 usecase = node_to_item(node, struct audio_usecase, list);
2285 if (usecase->id == uc_id)
2286 return usecase;
2287 }
2288 return NULL;
2289}
2290
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302291/*
2292 * is a true native playback active
2293 */
2294bool audio_is_true_native_stream_active(struct audio_device *adev)
2295{
2296 bool active = false;
2297 int i = 0;
2298 struct listnode *node;
2299
2300 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2301 ALOGV("%s:napb: not in true mode or non hdphones device",
2302 __func__);
2303 active = false;
2304 goto exit;
2305 }
2306
2307 list_for_each(node, &adev->usecase_list) {
2308 struct audio_usecase *uc;
2309 uc = node_to_item(node, struct audio_usecase, list);
2310 struct stream_out *curr_out =
2311 (struct stream_out*) uc->stream.out;
2312
2313 if (curr_out && PCM_PLAYBACK == uc->type) {
2314 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2315 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2316 uc->id, curr_out->sample_rate,
2317 curr_out->bit_width,
2318 platform_get_snd_device_name(uc->out_snd_device));
2319
2320 if (is_offload_usecase(uc->id) &&
2321 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2322 active = true;
2323 ALOGD("%s:napb:native stream detected", __func__);
2324 }
2325 }
2326 }
2327exit:
2328 return active;
2329}
2330
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002331uint32_t adev_get_dsp_bit_width_enforce_mode()
2332{
2333 if (adev == NULL) {
2334 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2335 return 0;
2336 }
2337 return adev->dsp_bit_width_enforce_mode;
2338}
2339
2340static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2341{
2342 char value[PROPERTY_VALUE_MAX];
2343 int trial;
2344 uint32_t dsp_bit_width_enforce_mode = 0;
2345
2346 if (!mixer) {
2347 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2348 __func__);
2349 return 0;
2350 }
2351
2352 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2353 value, NULL) > 0) {
2354 trial = atoi(value);
2355 switch (trial) {
2356 case 16:
2357 dsp_bit_width_enforce_mode = 16;
2358 break;
2359 case 24:
2360 dsp_bit_width_enforce_mode = 24;
2361 break;
2362 case 32:
2363 dsp_bit_width_enforce_mode = 32;
2364 break;
2365 default:
2366 dsp_bit_width_enforce_mode = 0;
2367 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2368 break;
2369 }
2370 }
2371
2372 return dsp_bit_width_enforce_mode;
2373}
2374
2375static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2376 uint32_t enforce_mode,
2377 bool enable)
2378{
2379 struct mixer_ctl *ctl = NULL;
2380 const char *mixer_ctl_name = "ASM Bit Width";
2381 uint32_t asm_bit_width_mode = 0;
2382
2383 if (enforce_mode == 0) {
2384 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2385 return;
2386 }
2387
2388 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2389 if (!ctl) {
2390 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2391 __func__, mixer_ctl_name);
2392 return;
2393 }
2394
2395 if (enable)
2396 asm_bit_width_mode = enforce_mode;
2397 else
2398 asm_bit_width_mode = 0;
2399
2400 ALOGV("%s DSP bit width feature status is %d width=%d",
2401 __func__, enable, asm_bit_width_mode);
2402 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2403 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2404 asm_bit_width_mode);
2405
2406 return;
2407}
2408
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302409/*
2410 * if native DSD playback active
2411 */
2412bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2413{
2414 bool active = false;
2415 struct listnode *node = NULL;
2416 struct audio_usecase *uc = NULL;
2417 struct stream_out *curr_out = NULL;
2418
2419 list_for_each(node, &adev->usecase_list) {
2420 uc = node_to_item(node, struct audio_usecase, list);
2421 curr_out = (struct stream_out*) uc->stream.out;
2422
2423 if (curr_out && PCM_PLAYBACK == uc->type &&
2424 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2425 active = true;
2426 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302427 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302428 }
2429 }
2430 return active;
2431}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302432
2433static bool force_device_switch(struct audio_usecase *usecase)
2434{
2435 bool ret = false;
2436 bool is_it_true_mode = false;
2437
Zhou Song30f2c3e2018-02-08 14:02:15 +08002438 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302439 usecase->type == TRANSCODE_LOOPBACK_RX ||
2440 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002441 return false;
2442 }
2443
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002444 if(usecase->stream.out == NULL) {
2445 ALOGE("%s: stream.out is NULL", __func__);
2446 return false;
2447 }
2448
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302449 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002450 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002451 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2452 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302453 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2454 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2455 (!is_it_true_mode && adev->native_playback_enabled)){
2456 ret = true;
2457 ALOGD("napb: time to toggle native mode");
2458 }
2459 }
2460
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302461 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302462 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2463 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002464 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302465 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302466 ALOGD("Force a2dp device switch to update new encoder config");
2467 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002468 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302469
Florian Pfister1a84f312018-07-19 14:38:18 +02002470 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302471 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2472 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002473 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302474 return ret;
2475}
2476
Aalique Grahame22e49102018-12-18 14:23:57 -08002477static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2478{
2479 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2480}
2481
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302482bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2483{
2484 bool ret=false;
2485 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002486 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2487 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302488 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2489 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002490 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302491 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002492 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2493 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302494 ret = true;
2495
2496 return ret;
2497}
2498
2499bool is_a2dp_device(snd_device_t out_snd_device)
2500{
2501 bool ret=false;
2502 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2503 ret = true;
2504
2505 return ret;
2506}
2507
2508bool is_bt_soc_on(struct audio_device *adev)
2509{
2510 struct mixer_ctl *ctl;
2511 char *mixer_ctl_name = "BT SOC status";
2512 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2513 bool bt_soc_status = true;
2514 if (!ctl) {
2515 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2516 __func__, mixer_ctl_name);
2517 /*This is to ensure we dont break targets which dont have the kernel change*/
2518 return true;
2519 }
2520 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2521 ALOGD("BT SOC status: %d",bt_soc_status);
2522 return bt_soc_status;
2523}
2524
Zhou Song331c8e52019-08-26 14:16:12 +08002525static int configure_btsco_sample_rate(snd_device_t snd_device)
2526{
2527 struct mixer_ctl *ctl = NULL;
2528 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2529 char *rate_str = NULL;
2530 bool is_rx_dev = true;
2531
2532 if (is_btsco_device(snd_device, snd_device)) {
2533 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2534 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2535 if (!ctl_sr_tx || !ctl_sr_rx) {
2536 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2537 if (!ctl_sr)
2538 return -ENOSYS;
2539 }
2540
2541 switch (snd_device) {
2542 case SND_DEVICE_OUT_BT_SCO:
2543 rate_str = "KHZ_8";
2544 break;
2545 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2546 case SND_DEVICE_IN_BT_SCO_MIC:
2547 rate_str = "KHZ_8";
2548 is_rx_dev = false;
2549 break;
2550 case SND_DEVICE_OUT_BT_SCO_WB:
2551 rate_str = "KHZ_16";
2552 break;
2553 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2554 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2555 rate_str = "KHZ_16";
2556 is_rx_dev = false;
2557 break;
2558 default:
2559 return 0;
2560 }
2561
2562 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2563 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2564 return -ENOSYS;
2565 }
2566 return 0;
2567}
2568
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302569int out_standby_l(struct audio_stream *stream);
2570
Eric Laurent637e2d42018-11-15 12:24:31 -08002571struct stream_in *adev_get_active_input(const struct audio_device *adev)
2572{
2573 struct listnode *node;
2574 struct stream_in *last_active_in = NULL;
2575
2576 /* Get last added active input.
2577 * TODO: We may use a priority mechanism to pick highest priority active source */
2578 list_for_each(node, &adev->usecase_list)
2579 {
2580 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2581 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2582 last_active_in = usecase->stream.in;
2583 }
2584
2585 return last_active_in;
2586}
2587
2588struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2589{
2590 struct listnode *node;
2591
2592 /* First check active inputs with voice communication source and then
2593 * any input if audio mode is in communication */
2594 list_for_each(node, &adev->usecase_list)
2595 {
2596 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2597 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2598 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2599 return usecase->stream.in;
2600 }
2601 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2602 return adev_get_active_input(adev);
2603
2604 return NULL;
2605}
2606
Carter Hsu2e429db2019-05-14 18:50:52 +08002607/*
2608 * Aligned with policy.h
2609 */
2610static inline int source_priority(int inputSource)
2611{
2612 switch (inputSource) {
2613 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2614 return 9;
2615 case AUDIO_SOURCE_CAMCORDER:
2616 return 8;
2617 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2618 return 7;
2619 case AUDIO_SOURCE_UNPROCESSED:
2620 return 6;
2621 case AUDIO_SOURCE_MIC:
2622 return 5;
2623 case AUDIO_SOURCE_ECHO_REFERENCE:
2624 return 4;
2625 case AUDIO_SOURCE_FM_TUNER:
2626 return 3;
2627 case AUDIO_SOURCE_VOICE_RECOGNITION:
2628 return 2;
2629 case AUDIO_SOURCE_HOTWORD:
2630 return 1;
2631 default:
2632 break;
2633 }
2634 return 0;
2635}
2636
2637static struct stream_in *get_priority_input(struct audio_device *adev)
2638{
2639 struct listnode *node;
2640 struct audio_usecase *usecase;
2641 int last_priority = 0, priority;
2642 struct stream_in *priority_in = NULL;
2643 struct stream_in *in;
2644
2645 list_for_each(node, &adev->usecase_list) {
2646 usecase = node_to_item(node, struct audio_usecase, list);
2647 if (usecase->type == PCM_CAPTURE) {
2648 in = usecase->stream.in;
2649 if (!in)
2650 continue;
2651 priority = source_priority(in->source);
2652
2653 if (priority > last_priority) {
2654 last_priority = priority;
2655 priority_in = in;
2656 }
2657 }
2658 }
2659 return priority_in;
2660}
2661
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002662int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002664 snd_device_t out_snd_device = SND_DEVICE_NONE;
2665 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002666 struct audio_usecase *usecase = NULL;
2667 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002668 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002669 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302670 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002671 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002672 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302674 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2675
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 usecase = get_usecase_from_list(adev, uc_id);
2677 if (usecase == NULL) {
2678 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2679 return -EINVAL;
2680 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002682 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002683 (usecase->type == VOIP_CALL) ||
2684 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302685 if(usecase->stream.out == NULL) {
2686 ALOGE("%s: stream.out is NULL", __func__);
2687 return -EINVAL;
2688 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002689 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002690 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2691 uc_id);
2692 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2693 uc_id);
2694 } else {
2695 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302696 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002697 in_snd_device = platform_get_input_snd_device(adev->platform,
2698 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302699 &usecase->stream.out->device_list,
2700 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002701 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002702 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302703 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302704 if (usecase->stream.inout == NULL) {
2705 ALOGE("%s: stream.inout is NULL", __func__);
2706 return -EINVAL;
2707 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002708 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302709 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2710 stream_out.format = usecase->stream.inout->out_config.format;
2711 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302712 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002713 assign_devices(&usecase->device_list,
2714 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302715 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2716 if (usecase->stream.inout == NULL) {
2717 ALOGE("%s: stream.inout is NULL", __func__);
2718 return -EINVAL;
2719 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302720 struct listnode out_devices;
2721 list_init(&out_devices);
2722 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2723 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002724 assign_devices(&usecase->device_list,
2725 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002726 } else {
2727 /*
2728 * If the voice call is active, use the sound devices of voice call usecase
2729 * so that it would not result any device switch. All the usecases will
2730 * be switched to new device when select_devices() is called for voice call
2731 * usecase. This is to avoid switching devices for voice call when
2732 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002733 * choose voice call device only if the use case device is
2734 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002735 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002736 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002737 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002738 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002739 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2740 is_codec_backend_out_device_type(&usecase->device_list)) ||
2741 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2742 is_codec_backend_in_device_type(&usecase->device_list)) ||
2743 is_single_device_type_equal(&vc_usecase->device_list,
2744 AUDIO_DEVICE_OUT_HEARING_AID) ||
2745 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002746 AUDIO_DEVICE_IN_VOICE_CALL) ||
2747 (is_single_device_type_equal(&usecase->device_list,
2748 AUDIO_DEVICE_IN_USB_HEADSET) &&
2749 is_single_device_type_equal(&vc_usecase->device_list,
2750 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002751 in_snd_device = vc_usecase->in_snd_device;
2752 out_snd_device = vc_usecase->out_snd_device;
2753 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002754 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002755 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002756 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002757 if ((voip_usecase != NULL) &&
2758 (usecase->type == PCM_PLAYBACK) &&
2759 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002760 out_snd_device_backend_match = platform_check_backends_match(
2761 voip_usecase->out_snd_device,
2762 platform_get_output_snd_device(
2763 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302764 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002765 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002766 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2767 (is_codec_backend_out_device_type(&usecase->device_list) ||
2768 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002769 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002770 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002771 in_snd_device = voip_usecase->in_snd_device;
2772 out_snd_device = voip_usecase->out_snd_device;
2773 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002774 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002775 hfp_ucid = audio_extn_hfp_get_usecase();
2776 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002777 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002778 in_snd_device = hfp_usecase->in_snd_device;
2779 out_snd_device = hfp_usecase->out_snd_device;
2780 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002781 }
2782 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302783 if (usecase->stream.out == NULL) {
2784 ALOGE("%s: stream.out is NULL", __func__);
2785 return -EINVAL;
2786 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002787 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002788 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002789 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002790 struct stream_out *voip_out = adev->primary_output;
2791 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002792 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002793 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2794 else
2795 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302796 usecase->stream.out,
2797 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002798 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002799
Eric Laurent637e2d42018-11-15 12:24:31 -08002800 if (voip_usecase)
2801 voip_out = voip_usecase->stream.out;
2802
2803 if (usecase->stream.out == voip_out && voip_in != NULL)
2804 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002805 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002806 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302807 if (usecase->stream.in == NULL) {
2808 ALOGE("%s: stream.in is NULL", __func__);
2809 return -EINVAL;
2810 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002811 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002812 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002813 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002816 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002817
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002818 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002819 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002820 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2821 USECASE_AUDIO_PLAYBACK_VOIP);
2822
Carter Hsu2e429db2019-05-14 18:50:52 +08002823 usecase->stream.in->enable_ec_port = false;
2824
Zhou Song62ea0282020-03-22 19:53:01 +08002825 bool is_ha_usecase = adev->ha_proxy_enable ?
2826 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2827 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2828 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002829 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002830 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002831 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002832 } else if (adev->primary_output &&
2833 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002834 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002835 } else {
2836 /* forcing speaker o/p device to get matching i/p pair
2837 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002838 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002839 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002840 priority_in = voip_in;
2841 } else {
2842 /* get the input with the highest priority source*/
2843 priority_in = get_priority_input(adev);
2844
2845 if (!priority_in)
2846 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002847 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002848
Eric Laurent637e2d42018-11-15 12:24:31 -08002849 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002850 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302851 &out_devices,
2852 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002853 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002854 }
2855 }
2856
2857 if (out_snd_device == usecase->out_snd_device &&
2858 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302859
2860 if (!force_device_switch(usecase))
2861 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862 }
2863
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002864 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002865 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002866 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002867 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2868 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302869 }
2870
Aalique Grahame22e49102018-12-18 14:23:57 -08002871 if (out_snd_device != SND_DEVICE_NONE &&
2872 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2873 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2874 __func__,
2875 use_case_table[uc_id],
2876 adev->last_logged_snd_device[uc_id][0],
2877 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2878 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2879 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2880 -1,
2881 out_snd_device,
2882 platform_get_snd_device_name(out_snd_device),
2883 platform_get_snd_device_acdb_id(out_snd_device));
2884 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2885 }
2886 if (in_snd_device != SND_DEVICE_NONE &&
2887 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2888 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2889 __func__,
2890 use_case_table[uc_id],
2891 adev->last_logged_snd_device[uc_id][1],
2892 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2893 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2894 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2895 -1,
2896 in_snd_device,
2897 platform_get_snd_device_name(in_snd_device),
2898 platform_get_snd_device_acdb_id(in_snd_device));
2899 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2900 }
2901
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903 /*
2904 * Limitation: While in call, to do a device switch we need to disable
2905 * and enable both RX and TX devices though one of them is same as current
2906 * device.
2907 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002908 if ((usecase->type == VOICE_CALL) &&
2909 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2910 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002911 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002912 }
2913
2914 if (((usecase->type == VOICE_CALL) ||
2915 (usecase->type == VOIP_CALL)) &&
2916 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2917 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302918 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002919 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002920 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002921
2922 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302923 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002924 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002925 }
2926
Aalique Grahame22e49102018-12-18 14:23:57 -08002927 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2928 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002929 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302930 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002931 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2932 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2933 else
2934 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302935 }
2936
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002937 /* Disable current sound devices */
2938 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002939 disable_audio_route(adev, usecase);
2940 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 }
2942
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002943 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002944 disable_audio_route(adev, usecase);
2945 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 }
2947
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002948 /* Applicable only on the targets that has external modem.
2949 * New device information should be sent to modem before enabling
2950 * the devices to reduce in-call device switch time.
2951 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002952 if ((usecase->type == VOICE_CALL) &&
2953 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2954 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002955 status = platform_switch_voice_call_enable_device_config(adev->platform,
2956 out_snd_device,
2957 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002958 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002960 /* Enable new sound devices */
2961 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002962 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302963 if (platform_check_codec_asrc_support(adev->platform))
2964 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002965 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08002966 /* Enable haptics device for haptic usecase */
2967 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
2968 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 }
2970
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002971 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302972 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002973 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002974 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002975
Avinash Vaish71a8b972014-07-24 15:36:33 +05302976 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002977 status = platform_switch_voice_call_device_post(adev->platform,
2978 out_snd_device,
2979 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302980 enable_audio_route_for_voice_usecases(adev, usecase);
2981 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002982
sangwoo170731f2013-06-08 15:36:36 +09002983 usecase->in_snd_device = in_snd_device;
2984 usecase->out_snd_device = out_snd_device;
2985
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302986 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2987 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302988 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002989 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002990 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002991 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2992 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2993 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2994 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2995 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2996 /*
2997 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2998 * configured device sample rate, if not update the COPP rate to be equal to the
2999 * device sample rate, else open COPP at stream sample rate
3000 */
3001 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3002 usecase->stream.out->sample_rate,
3003 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303004 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303005 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3006 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303007 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003008 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3009 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3010 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3011 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003012 }
3013 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003014
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003015 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003016
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003017 /* If input stream is already running then effect needs to be
3018 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003019 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003020 check_and_enable_effect(adev);
3021
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003022 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003023 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303024 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003025 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3026
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003027 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303028 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003029 voice_extn_compress_voip_is_started(adev))
3030 voice_set_sidetone(adev, out_snd_device, true);
3031 }
3032
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003033 /* Applicable only on the targets that has external modem.
3034 * Enable device command should be sent to modem only after
3035 * enabling voice call mixer controls
3036 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003037 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003038 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3039 out_snd_device,
3040 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303041
3042 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003043 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303044 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003045 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303046 if (is_bt_soc_on(adev) == false){
3047 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003048 if (in->pcm != NULL)
3049 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303050 }
3051 }
3052 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3053 && usecase->stream.out->started) {
3054 if (is_bt_soc_on(adev) == false) {
3055 ALOGD("BT SCO/A2DP disconnected while in connection");
3056 out_standby_l(&usecase->stream.out->stream.common);
3057 }
3058 }
3059 } else if ((usecase->stream.out != NULL) &&
3060 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303061 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3062 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003063 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303064 usecase->stream.out->started) {
3065 if (is_bt_soc_on(adev) == false) {
3066 ALOGD("BT SCO/A2dp disconnected while in connection");
3067 out_standby_l(&usecase->stream.out->stream.common);
3068 }
3069 }
3070 }
3071
Yung Ti Su70cb8242018-06-22 17:38:47 +08003072 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003073 struct stream_out *voip_out = voip_usecase->stream.out;
3074 audio_extn_utils_send_app_type_gain(adev,
3075 voip_out->app_type_cfg.app_type,
3076 &voip_out->app_type_cfg.gain[0]);
3077 }
3078
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003079 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 return status;
3082}
3083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084static int stop_input_stream(struct stream_in *in)
3085{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303086 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303088
3089 if (in == NULL) {
3090 ALOGE("%s: stream_in ptr is NULL", __func__);
3091 return -EINVAL;
3092 }
3093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003095 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096
Eric Laurent994a6932013-07-17 11:51:42 -07003097 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003098 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 uc_info = get_usecase_from_list(adev, in->usecase);
3100 if (uc_info == NULL) {
3101 ALOGE("%s: Could not find the usecase (%d) in the list",
3102 __func__, in->usecase);
3103 return -EINVAL;
3104 }
3105
Carter Hsu2e429db2019-05-14 18:50:52 +08003106 priority_in = get_priority_input(adev);
3107
Derek Chenea197282019-01-07 17:35:01 -08003108 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3109 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003110
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003111 /* Close in-call recording streams */
3112 voice_check_and_stop_incall_rec_usecase(adev, in);
3113
Eric Laurent150dbfe2013-02-27 14:31:02 -08003114 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003115 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003116
3117 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003118 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003120 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303121 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3122
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003123 list_remove(&uc_info->list);
3124 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125
Carter Hsu2e429db2019-05-14 18:50:52 +08003126 if (priority_in == in) {
3127 priority_in = get_priority_input(adev);
3128 if (priority_in)
3129 select_devices(adev, priority_in->usecase);
3130 }
3131
Vatsal Buchac09ae062018-11-14 13:25:08 +05303132 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003133 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 return ret;
3135}
3136
3137int start_input_stream(struct stream_in *in)
3138{
3139 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003140 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303142
3143 if (in == NULL) {
3144 ALOGE("%s: stream_in ptr is NULL", __func__);
3145 return -EINVAL;
3146 }
3147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003149 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003150 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151
Mingming Yin2664a5b2015-09-03 10:53:11 -07003152 if (get_usecase_from_list(adev, usecase) == NULL)
3153 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303154 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3155 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003156
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303157 if (CARD_STATUS_OFFLINE == in->card_status||
3158 CARD_STATUS_OFFLINE == adev->card_status) {
3159 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303160 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 goto error_config;
3162 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303163
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003164 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303165 if (!adev->bt_sco_on) {
3166 ALOGE("%s: SCO profile is not ready, return error", __func__);
3167 ret = -EIO;
3168 goto error_config;
3169 }
3170 }
3171
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003172 /* Check if source matches incall recording usecase criteria */
3173 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3174 if (ret)
3175 goto error_config;
3176 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003177 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3178
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303179 if (audio_extn_cin_attached_usecase(in))
3180 audio_extn_cin_acquire_usecase(in);
3181
Mingming Yin2664a5b2015-09-03 10:53:11 -07003182 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3183 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3184 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003185 ret = -EINVAL;
3186 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003187 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003188
Eric Laurentb23d5282013-05-14 15:27:20 -07003189 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 if (in->pcm_device_id < 0) {
3191 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3192 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003193 ret = -EINVAL;
3194 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003198
3199 if (!uc_info) {
3200 ret = -ENOMEM;
3201 goto error_config;
3202 }
3203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 uc_info->id = in->usecase;
3205 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003206 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003207 list_init(&uc_info->device_list);
3208 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003209 uc_info->in_snd_device = SND_DEVICE_NONE;
3210 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003212 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003213 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303214 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3215 adev->perf_lock_opts,
3216 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003217 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Derek Chenea197282019-01-07 17:35:01 -08003219 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3220 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003221
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303222 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3223
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303224 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303225 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303226 if (ret)
3227 goto error_open;
3228 else
3229 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003230 }
3231
Haynes Mathew George16081042017-05-31 17:16:49 -07003232 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003233 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003234 ALOGE("%s: pcm stream not ready", __func__);
3235 goto error_open;
3236 }
3237 ret = pcm_start(in->pcm);
3238 if (ret < 0) {
3239 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3240 goto error_open;
3241 }
3242 } else {
3243 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3244 unsigned int pcm_open_retry_count = 0;
3245
Zhou Song62ea0282020-03-22 19:53:01 +08003246 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3247 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003248 flags |= PCM_MMAP | PCM_NOIRQ;
3249 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3250 } else if (in->realtime) {
3251 flags |= PCM_MMAP | PCM_NOIRQ;
3252 }
3253
Garmond Leunge2433c32017-09-28 21:51:22 -07003254 if (audio_extn_ffv_get_stream() == in) {
3255 ALOGD("%s: ffv stream, update pcm config", __func__);
3256 audio_extn_ffv_update_pcm_config(&config);
3257 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003258 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3259 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3260
3261 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003262 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003263 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003264 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003265 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303266 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303267 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3268 adev->card_status = CARD_STATUS_OFFLINE;
3269 in->card_status = CARD_STATUS_OFFLINE;
3270 ret = -EIO;
3271 goto error_open;
3272 }
3273
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3275 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3276 if (in->pcm != NULL) {
3277 pcm_close(in->pcm);
3278 in->pcm = NULL;
3279 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003280 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003281 ret = -EIO;
3282 goto error_open;
3283 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003284 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003285 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3286 continue;
3287 }
3288 break;
3289 }
3290
3291 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003292 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003293 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003294 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003295 if (ret < 0) {
3296 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3297 pcm_close(in->pcm);
3298 in->pcm = NULL;
3299 goto error_open;
3300 }
3301 register_in_stream(in);
3302 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003303 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003304 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003305 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003306 if (ret < 0) {
3307 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003308 pcm_close(in->pcm);
3309 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003310 goto error_open;
3311 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003312 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003313 }
3314
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003315 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003316 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3317 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003318
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003319 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303320 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3321
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303322done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003323 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303324 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003325 ALOGV("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303326 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003327 return ret;
3328
3329error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003330 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303331 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003333
Eric Laurentc8400632013-02-14 19:04:54 -08003334error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003335 if (audio_extn_cin_attached_usecase(in))
3336 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303337 /*
3338 * sleep 50ms to allow sufficient time for kernel
3339 * drivers to recover incases like SSR.
3340 */
3341 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003342 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303343 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003347void lock_input_stream(struct stream_in *in)
3348{
3349 pthread_mutex_lock(&in->pre_lock);
3350 pthread_mutex_lock(&in->lock);
3351 pthread_mutex_unlock(&in->pre_lock);
3352}
3353
3354void lock_output_stream(struct stream_out *out)
3355{
3356 pthread_mutex_lock(&out->pre_lock);
3357 pthread_mutex_lock(&out->lock);
3358 pthread_mutex_unlock(&out->pre_lock);
3359}
3360
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003361/* must be called with out->lock locked */
3362static int send_offload_cmd_l(struct stream_out* out, int command)
3363{
3364 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3365
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003366 if (!cmd) {
3367 ALOGE("failed to allocate mem for command 0x%x", command);
3368 return -ENOMEM;
3369 }
3370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 ALOGVV("%s %d", __func__, command);
3372
3373 cmd->cmd = command;
3374 list_add_tail(&out->offload_cmd_list, &cmd->node);
3375 pthread_cond_signal(&out->offload_cond);
3376 return 0;
3377}
3378
Weiyin Jiang280ea742020-09-08 20:28:22 +08003379/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380static void stop_compressed_output_l(struct stream_out *out)
3381{
3382 out->offload_state = OFFLOAD_STATE_IDLE;
3383 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003384 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 if (out->compr != NULL) {
3386 compress_stop(out->compr);
3387 while (out->offload_thread_blocked) {
3388 pthread_cond_wait(&out->cond, &out->lock);
3389 }
3390 }
3391}
3392
Varun Balaraje49253e2017-07-06 19:48:56 +05303393bool is_interactive_usecase(audio_usecase_t uc_id)
3394{
3395 unsigned int i;
3396 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3397 if (uc_id == interactive_usecases[i])
3398 return true;
3399 }
3400 return false;
3401}
3402
3403static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3404{
3405 audio_usecase_t ret_uc = USECASE_INVALID;
3406 unsigned int intract_uc_index;
3407 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3408
3409 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3410 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3411 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3412 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3413 ret_uc = interactive_usecases[intract_uc_index];
3414 break;
3415 }
3416 }
3417
3418 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3419 return ret_uc;
3420}
3421
3422static void free_interactive_usecase(struct audio_device *adev,
3423 audio_usecase_t uc_id)
3424{
3425 unsigned int interact_uc_index;
3426 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3427
3428 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3429 if (interactive_usecases[interact_uc_index] == uc_id) {
3430 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3431 break;
3432 }
3433 }
3434 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3435}
3436
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003437bool is_offload_usecase(audio_usecase_t uc_id)
3438{
3439 unsigned int i;
3440 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3441 if (uc_id == offload_usecases[i])
3442 return true;
3443 }
3444 return false;
3445}
3446
Dhananjay Kumarac341582017-02-23 23:42:25 +05303447static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003448{
vivek mehta446c3962015-09-14 10:57:35 -07003449 audio_usecase_t ret_uc = USECASE_INVALID;
3450 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003451 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003452 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303453 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003454 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3455 else
3456 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003457
vivek mehta446c3962015-09-14 10:57:35 -07003458 pthread_mutex_lock(&adev->lock);
3459 if (get_usecase_from_list(adev, ret_uc) != NULL)
3460 ret_uc = USECASE_INVALID;
3461 pthread_mutex_unlock(&adev->lock);
3462
3463 return ret_uc;
3464 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003465
3466 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003467 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3468 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3469 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3470 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003471 break;
3472 }
3473 }
vivek mehta446c3962015-09-14 10:57:35 -07003474
3475 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3476 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003477}
3478
3479static void free_offload_usecase(struct audio_device *adev,
3480 audio_usecase_t uc_id)
3481{
vivek mehta446c3962015-09-14 10:57:35 -07003482 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003483 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003484
3485 if (!adev->multi_offload_enable)
3486 return;
3487
3488 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3489 if (offload_usecases[offload_uc_index] == uc_id) {
3490 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003491 break;
3492 }
3493 }
3494 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3495}
3496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497static void *offload_thread_loop(void *context)
3498{
3499 struct stream_out *out = (struct stream_out *) context;
3500 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003501 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003503 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003504 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3506
3507 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003508 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003509 out->offload_state = OFFLOAD_STATE_IDLE;
3510 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 for (;;) {
3512 struct offload_cmd *cmd = NULL;
3513 stream_callback_event_t event;
3514 bool send_callback = false;
3515
3516 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3517 __func__, list_empty(&out->offload_cmd_list),
3518 out->offload_state);
3519 if (list_empty(&out->offload_cmd_list)) {
3520 ALOGV("%s SLEEPING", __func__);
3521 pthread_cond_wait(&out->offload_cond, &out->lock);
3522 ALOGV("%s RUNNING", __func__);
3523 continue;
3524 }
3525
3526 item = list_head(&out->offload_cmd_list);
3527 cmd = node_to_item(item, struct offload_cmd, node);
3528 list_remove(item);
3529
3530 ALOGVV("%s STATE %d CMD %d out->compr %p",
3531 __func__, out->offload_state, cmd->cmd, out->compr);
3532
3533 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3534 free(cmd);
3535 break;
3536 }
3537
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003538 // allow OFFLOAD_CMD_ERROR reporting during standby
3539 // this is needed to handle failures during compress_open
3540 // Note however that on a pause timeout, the stream is closed
3541 // and no offload usecase will be active. Therefore this
3542 // special case is needed for compress_open failures alone
3543 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3544 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003545 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003546 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547 pthread_cond_signal(&out->cond);
3548 continue;
3549 }
3550 out->offload_thread_blocked = true;
3551 pthread_mutex_unlock(&out->lock);
3552 send_callback = false;
3553 switch(cmd->cmd) {
3554 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003555 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003557 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 send_callback = true;
3559 event = STREAM_CBK_EVENT_WRITE_READY;
3560 break;
3561 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003562 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303563 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003564 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303565 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003566 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303567 if (ret < 0)
3568 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303569 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303570 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003571 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003572 else
3573 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003574 if (-ENETRESET != ret && !(-EINTR == ret &&
3575 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303576 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303577 pthread_mutex_lock(&out->lock);
3578 out->send_new_metadata = 1;
3579 out->send_next_track_params = true;
3580 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303581 event = STREAM_CBK_EVENT_DRAIN_READY;
3582 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3583 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303584 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003585 break;
3586 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003587 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003588 ret = compress_drain(out->compr);
3589 ALOGD("copl(%p):out of compress_drain", out);
3590 // EINTR check avoids drain interruption due to SSR
3591 if (-ENETRESET != ret && !(-EINTR == ret &&
3592 CARD_STATUS_OFFLINE == out->card_status)) {
3593 send_callback = true;
3594 event = STREAM_CBK_EVENT_DRAIN_READY;
3595 } else
3596 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003597 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303598 case OFFLOAD_CMD_ERROR:
3599 ALOGD("copl(%p): sending error callback to AF", out);
3600 send_callback = true;
3601 event = STREAM_CBK_EVENT_ERROR;
3602 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603 default:
3604 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3605 break;
3606 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003607 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608 out->offload_thread_blocked = false;
3609 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003610 if (send_callback && out->client_callback) {
3611 ALOGVV("%s: sending client_callback event %d", __func__, event);
3612 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003613 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003614 free(cmd);
3615 }
3616
3617 pthread_cond_signal(&out->cond);
3618 while (!list_empty(&out->offload_cmd_list)) {
3619 item = list_head(&out->offload_cmd_list);
3620 list_remove(item);
3621 free(node_to_item(item, struct offload_cmd, node));
3622 }
3623 pthread_mutex_unlock(&out->lock);
3624
3625 return NULL;
3626}
3627
3628static int create_offload_callback_thread(struct stream_out *out)
3629{
3630 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3631 list_init(&out->offload_cmd_list);
3632 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3633 offload_thread_loop, out);
3634 return 0;
3635}
3636
3637static int destroy_offload_callback_thread(struct stream_out *out)
3638{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003639 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08003640 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003641 stop_compressed_output_l(out);
3642 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3643
Weiyin Jiang280ea742020-09-08 20:28:22 +08003644 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645 pthread_mutex_unlock(&out->lock);
3646 pthread_join(out->offload_thread, (void **) NULL);
3647 pthread_cond_destroy(&out->offload_cond);
3648
3649 return 0;
3650}
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652static int stop_output_stream(struct stream_out *out)
3653{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303654 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 struct audio_usecase *uc_info;
3656 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003657 bool has_voip_usecase =
3658 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659
Eric Laurent994a6932013-07-17 11:51:42 -07003660 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003661 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 uc_info = get_usecase_from_list(adev, out->usecase);
3663 if (uc_info == NULL) {
3664 ALOGE("%s: Could not find the usecase (%d) in the list",
3665 __func__, out->usecase);
3666 return -EINVAL;
3667 }
3668
Derek Chenea197282019-01-07 17:35:01 -08003669 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3670 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003671
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003672 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303673 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003674 if (adev->visualizer_stop_output != NULL)
3675 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003676
3677 audio_extn_dts_remove_state_notifier_node(out->usecase);
3678
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003679 if (adev->offload_effects_stop_output != NULL)
3680 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003681 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3682 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3683 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003684 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003685
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003686 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3687 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003688 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003689 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003690
Eric Laurent150dbfe2013-02-27 14:31:02 -08003691 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003692 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003693
3694 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003695 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003696 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3697 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698
Aalique Grahame22e49102018-12-18 14:23:57 -08003699 audio_extn_extspk_update(adev->extspk);
3700
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003701 if (is_offload_usecase(out->usecase)) {
3702 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3703 adev->dsp_bit_width_enforce_mode,
3704 false);
3705 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003706 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003707 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3708 false);
3709
3710 if (ret != 0)
3711 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3712 /* default service interval was successfully updated,
3713 reopen USB backend with new service interval */
3714 ret = 0;
3715 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003716
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003717 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303718 out->started = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08003719 pthread_mutex_lock(&out->latch_lock);
3720 out->muted = false;
3721 pthread_mutex_unlock(&out->latch_lock);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003722 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303723 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003724 ALOGV("Disable passthrough , reset mixer to pcm");
3725 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003726#ifdef AUDIO_GKI_ENABLED
3727 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3728 out->compr_config.codec->reserved[0] = 0;
3729#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003730 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003731#endif
Mingming Yin21854652016-04-13 11:54:02 -07003732 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003733 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3734 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003735
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303736 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003737 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303738 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303739
Manish Dewangan21a850a2017-08-14 12:03:55 +05303740 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003741 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3742 if (ret < 0)
3743 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3744 }
3745
juyuchen2d415992018-11-16 14:15:16 +08003746 /* 1) media + voip output routing to handset must route media back to
3747 speaker when voip stops.
3748 2) trigger voip input to reroute when voip output changes to
3749 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003750 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003751 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003752 struct listnode *node;
3753 struct audio_usecase *usecase;
3754 list_for_each(node, &adev->usecase_list) {
3755 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003756 if ((usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303757 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
3758 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY)
juyuchen2d415992018-11-16 14:15:16 +08003759 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003760 continue;
3761
3762 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3763 __func__, usecase->id, use_case_table[usecase->id],
3764 out->usecase, use_case_table[out->usecase]);
3765 select_devices(adev, usecase->id);
3766 }
3767 }
3768
Garmond Leung5fd0b552018-04-17 11:56:12 -07003769 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003770 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 return ret;
3772}
3773
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003774struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3775 unsigned int flags, unsigned int pcm_open_retry_count,
3776 struct pcm_config *config)
3777{
3778 struct pcm* pcm = NULL;
3779
3780 while (1) {
3781 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3782 if (pcm == NULL || !pcm_is_ready(pcm)) {
3783 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3784 if (pcm != NULL) {
3785 pcm_close(pcm);
3786 pcm = NULL;
3787 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003788 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003789 return NULL;
3790
Weiyin Jiang72197252019-10-09 11:49:32 +08003791 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003792 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3793 continue;
3794 }
3795 break;
3796 }
3797
3798 if (pcm_is_ready(pcm)) {
3799 int ret = pcm_prepare(pcm);
3800 if (ret < 0) {
3801 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3802 pcm_close(pcm);
3803 pcm = NULL;
3804 }
3805 }
3806
3807 return pcm;
3808}
3809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810int start_output_stream(struct stream_out *out)
3811{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 struct audio_usecase *uc_info;
3814 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003815 char mixer_ctl_name[128];
3816 struct mixer_ctl *ctl = NULL;
3817 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303818 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003819 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820
Haynes Mathew George380745d2017-10-04 15:27:45 -07003821 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003822 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3823 ret = -EINVAL;
3824 goto error_config;
3825 }
3826
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003827 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303828 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003829 get_device_types(&out->device_list), is_haptic_usecase);
3830
3831 bool is_speaker_active = compare_device_type(&out->device_list,
3832 AUDIO_DEVICE_OUT_SPEAKER);
3833 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3834 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303835
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303836 if (CARD_STATUS_OFFLINE == out->card_status ||
3837 CARD_STATUS_OFFLINE == adev->card_status) {
3838 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303839 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003840 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303841 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303842
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003843 //Update incall music usecase to reflect correct voice session
3844 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3845 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3846 if (ret != 0) {
3847 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3848 __func__, ret);
3849 goto error_config;
3850 }
3851 }
3852
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003853 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003854 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003855 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303856 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303857 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303858 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3859 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3860 ret = -EAGAIN;
3861 goto error_config;
3862 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303863 }
3864 }
3865 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003866 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303867 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003868 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303869 //combo usecase just by pass a2dp
3870 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003871 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303872 } else {
3873 ALOGE("%s: SCO profile is not ready, return error", __func__);
3874 ret = -EAGAIN;
3875 goto error_config;
3876 }
3877 }
3878 }
3879
Eric Laurentb23d5282013-05-14 15:27:20 -07003880 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 if (out->pcm_device_id < 0) {
3882 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3883 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003884 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003885 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 }
3887
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003888 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003889 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3890 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003891 if (adev->haptic_pcm_device_id < 0) {
3892 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3893 __func__, adev->haptic_pcm_device_id, out->usecase);
3894 ret = -EINVAL;
3895 goto error_config;
3896 }
3897 }
3898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003900
3901 if (!uc_info) {
3902 ret = -ENOMEM;
3903 goto error_config;
3904 }
3905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 uc_info->id = out->usecase;
3907 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003908 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003909 list_init(&uc_info->device_list);
3910 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003911 uc_info->in_snd_device = SND_DEVICE_NONE;
3912 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003913
3914 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003915 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003916 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3917 /* USB backend is not reopened immediately.
3918 This is eventually done as part of select_devices */
3919 }
3920
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003921 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922
Wei Wangf7ca6c92017-11-21 14:51:20 -08003923 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303924 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3925 adev->perf_lock_opts,
3926 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303927
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003928 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303929 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303930 if (audio_extn_passthru_is_enabled() &&
3931 audio_extn_passthru_is_passthrough_stream(out)) {
3932 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303933 }
3934 }
3935
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003936 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003937 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303938 if (!a2dp_combo) {
3939 check_a2dp_restore_l(adev, out, false);
3940 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003941 struct listnode dev;
3942 list_init(&dev);
3943 assign_devices(&dev, &out->device_list);
3944 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3945 reassign_device_list(&out->device_list,
3946 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003947 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003948 reassign_device_list(&out->device_list,
3949 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303950 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003951 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303952 }
3953 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303954 select_devices(adev, out->usecase);
3955 if (is_a2dp_out_device_type(&out->device_list) &&
3956 !adev->a2dp_started) {
3957 if (is_speaker_active || is_speaker_safe_active) {
3958 struct listnode dev;
3959 list_init(&dev);
3960 assign_devices(&dev, &out->device_list);
3961 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3962 reassign_device_list(&out->device_list,
3963 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3964 else
3965 reassign_device_list(&out->device_list,
3966 AUDIO_DEVICE_OUT_SPEAKER, "");
3967 select_devices(adev, out->usecase);
3968 assign_devices(&out->device_list, &dev);
3969 } else {
3970 ret = -EINVAL;
3971 goto error_open;
3972 }
3973 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303974 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003975
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003976 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3977 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003978 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003979 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003980
Derek Chenea197282019-01-07 17:35:01 -08003981 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3982 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003983
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003984 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3985 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003986
3987 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003988 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003989 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3990 ALOGE("%s: pcm stream not ready", __func__);
3991 goto error_open;
3992 }
3993 ret = pcm_start(out->pcm);
3994 if (ret < 0) {
3995 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3996 goto error_open;
3997 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003998 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003999 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004000 unsigned int flags = PCM_OUT;
4001 unsigned int pcm_open_retry_count = 0;
4002 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4003 flags |= PCM_MMAP | PCM_NOIRQ;
4004 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004005 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004006 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004007 } else
4008 flags |= PCM_MONOTONIC;
4009
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004010 if ((adev->vr_audio_mode_enabled) &&
4011 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4012 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4013 "PCM_Dev %d Topology", out->pcm_device_id);
4014 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4015 if (!ctl) {
4016 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4017 __func__, mixer_ctl_name);
4018 } else {
4019 //if success use ULLPP
4020 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4021 __func__, mixer_ctl_name, out->pcm_device_id);
4022 //There is a still a possibility that some sessions
4023 // that request for FAST|RAW when 3D audio is active
4024 //can go through ULLPP. Ideally we expects apps to
4025 //listen to audio focus and stop concurrent playback
4026 //Also, we will look for mode flag (voice_in_communication)
4027 //before enabling the realtime flag.
4028 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4029 }
4030 }
4031
Surendar Karka91fa3682018-07-02 18:12:12 +05304032 if (out->realtime)
4033 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4034 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4035
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004036 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4037 flags, pcm_open_retry_count,
4038 &(out->config));
4039 if (out->pcm == NULL) {
4040 ret = -EIO;
4041 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004042 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004043
4044 if (is_haptic_usecase) {
4045 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4046 adev->haptic_pcm_device_id,
4047 flags, pcm_open_retry_count,
4048 &(adev->haptics_config));
4049 // failure to open haptics pcm shouldnt stop audio,
4050 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004051
4052 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4053 ALOGD("%s: enable haptic audio synchronization", __func__);
4054 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4055 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004056 }
4057
Surendar Karka91fa3682018-07-02 18:12:12 +05304058 if (!out->realtime)
4059 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304060 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004061
Zhou Song2b8f28f2017-09-11 10:51:38 +08004062 // apply volume for voip playback after path is set up
4063 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4064 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304065 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4066 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304067 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4068 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004069 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4070 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304071 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004073 /*
4074 * set custom channel map if:
4075 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4076 * 2. custom channel map has been set by client
4077 * else default channel map of FC/FR/FL can always be set to DSP
4078 */
4079 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4080 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4081 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004082 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4083 adev->dsp_bit_width_enforce_mode,
4084 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004086 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004087 out->compr = compress_open(adev->snd_card,
4088 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004089 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004090 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304091 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304092 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4093 adev->card_status = CARD_STATUS_OFFLINE;
4094 out->card_status = CARD_STATUS_OFFLINE;
4095 ret = -EIO;
4096 goto error_open;
4097 }
4098
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004099 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004100 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 compress_close(out->compr);
4102 out->compr = NULL;
4103 ret = -EIO;
4104 goto error_open;
4105 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304106 /* compress_open sends params of the track, so reset the flag here */
4107 out->is_compr_metadata_avail = false;
4108
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004109 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004110 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004111
Fred Oh3f43e742015-03-04 18:42:34 -08004112 /* Since small bufs uses blocking writes, a write will be blocked
4113 for the default max poll time (20s) in the event of an SSR.
4114 Reduce the poll time to observe and deal with SSR faster.
4115 */
Ashish Jain5106d362016-05-11 19:23:33 +05304116 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004117 compress_set_max_poll_wait(out->compr, 1000);
4118 }
4119
Manish Dewangan69426c82017-01-30 17:35:36 +05304120 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304121 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304122
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004123 audio_extn_dts_create_state_notifier_node(out->usecase);
4124 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4125 popcount(out->channel_mask),
4126 out->playback_started);
4127
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004128#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304129 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004130 audio_extn_dolby_send_ddp_endp_params(adev);
4131#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304132 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4133 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004134 if (adev->visualizer_start_output != NULL)
4135 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4136 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304137 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004138 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004139 }
Derek Chenf13dd492018-11-13 14:53:51 -08004140
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004141 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004142 /* Update cached volume from media to offload/direct stream */
4143 struct listnode *node = NULL;
4144 list_for_each(node, &adev->active_outputs_list) {
4145 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4146 streams_output_ctxt_t,
4147 list);
4148 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4149 out->volume_l = out_ctxt->output->volume_l;
4150 out->volume_r = out_ctxt->output->volume_r;
4151 }
4152 }
4153 out_set_compr_volume(&out->stream,
4154 out->volume_l, out->volume_r);
4155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004157
4158 if (ret == 0) {
4159 register_out_stream(out);
4160 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004161 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4162 ALOGE("%s: pcm stream not ready", __func__);
4163 goto error_open;
4164 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004165 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004166 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004167 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004168 if (ret < 0)
4169 goto error_open;
4170 }
4171 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004172 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304173 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004174 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004175
vivek mehtad15d2bf2019-05-17 13:35:10 -07004176 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4177 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4178 audio_low_latency_hint_start();
4179 }
4180
Manish Dewangan21a850a2017-08-14 12:03:55 +05304181 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004182 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004183 if (ret < 0)
4184 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4185 }
4186
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004187 // consider a scenario where on pause lower layers are tear down.
4188 // so on resume, swap mixer control need to be sent only when
4189 // backend is active, hence rather than sending from enable device
4190 // sending it from start of streamtream
4191
4192 platform_set_swap_channels(adev, true);
4193
Haynes Mathew George380745d2017-10-04 15:27:45 -07004194 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304195 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004196 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004197error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004198 if (adev->haptic_pcm) {
4199 pcm_close(adev->haptic_pcm);
4200 adev->haptic_pcm = NULL;
4201 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004202 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304203 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004205error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304206 /*
4207 * sleep 50ms to allow sufficient time for kernel
4208 * drivers to recover incases like SSR.
4209 */
4210 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004211error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004212 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304213 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004214 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215}
4216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217static int check_input_parameters(uint32_t sample_rate,
4218 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004219 int channel_count,
4220 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004222 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304224 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4225 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4226 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004227 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004228 !audio_extn_compr_cap_format_supported(format) &&
4229 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004230 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004231
Aalique Grahame22e49102018-12-18 14:23:57 -08004232 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4233 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4234 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4235 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4236 return -EINVAL;
4237 }
4238
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004239 switch (channel_count) {
4240 case 1:
4241 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304242 case 3:
4243 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004244 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004245 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304246 case 10:
4247 case 12:
4248 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004249 break;
4250 default:
4251 ret = -EINVAL;
4252 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
4254 switch (sample_rate) {
4255 case 8000:
4256 case 11025:
4257 case 12000:
4258 case 16000:
4259 case 22050:
4260 case 24000:
4261 case 32000:
4262 case 44100:
4263 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004264 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304265 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004266 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304267 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268 break;
4269 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004270 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271 }
4272
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004273 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274}
4275
Naresh Tanniru04f71882018-06-26 17:46:22 +05304276
4277/** Add a value in a list if not already present.
4278 * @return true if value was successfully inserted or already present,
4279 * false if the list is full and does not contain the value.
4280 */
4281static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4282 for (size_t i = 0; i < list_length; i++) {
4283 if (list[i] == value) return true; // value is already present
4284 if (list[i] == 0) { // no values in this slot
4285 list[i] = value;
4286 return true; // value inserted
4287 }
4288 }
4289 return false; // could not insert value
4290}
4291
4292/** Add channel_mask in supported_channel_masks if not already present.
4293 * @return true if channel_mask was successfully inserted or already present,
4294 * false if supported_channel_masks is full and does not contain channel_mask.
4295 */
4296static void register_channel_mask(audio_channel_mask_t channel_mask,
4297 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4298 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4299 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4300}
4301
4302/** Add format in supported_formats if not already present.
4303 * @return true if format was successfully inserted or already present,
4304 * false if supported_formats is full and does not contain format.
4305 */
4306static void register_format(audio_format_t format,
4307 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4308 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4309 "%s: stream can not declare supporting its format %x", __func__, format);
4310}
4311/** Add sample_rate in supported_sample_rates if not already present.
4312 * @return true if sample_rate was successfully inserted or already present,
4313 * false if supported_sample_rates is full and does not contain sample_rate.
4314 */
4315static void register_sample_rate(uint32_t sample_rate,
4316 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4317 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4318 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4319}
4320
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004321static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4322{
4323 uint32_t high = num1, low = num2, temp = 0;
4324
4325 if (!num1 || !num2)
4326 return 0;
4327
4328 if (num1 < num2) {
4329 high = num2;
4330 low = num1;
4331 }
4332
4333 while (low != 0) {
4334 temp = low;
4335 low = high % low;
4336 high = temp;
4337 }
4338 return (num1 * num2)/high;
4339}
4340
4341static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4342{
4343 uint32_t remainder = 0;
4344
4345 if (!multiplier)
4346 return num;
4347
4348 remainder = num % multiplier;
4349 if (remainder)
4350 num += (multiplier - remainder);
4351
4352 return num;
4353}
4354
Aalique Grahame22e49102018-12-18 14:23:57 -08004355static size_t get_stream_buffer_size(size_t duration_ms,
4356 uint32_t sample_rate,
4357 audio_format_t format,
4358 int channel_count,
4359 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360{
4361 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004362 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363
Aalique Grahame22e49102018-12-18 14:23:57 -08004364 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004365 if (is_low_latency)
4366 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304367
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004368 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004369 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370
Ralf Herzbd08d632018-09-28 15:50:49 +02004371 /* make sure the size is multiple of 32 bytes and additionally multiple of
4372 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004373 * At 48 kHz mono 16-bit PCM:
4374 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4375 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004376 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004377 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004378 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004379
4380 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381}
4382
Aalique Grahame22e49102018-12-18 14:23:57 -08004383static size_t get_input_buffer_size(uint32_t sample_rate,
4384 audio_format_t format,
4385 int channel_count,
4386 bool is_low_latency)
4387{
4388 /* Don't know if USB HIFI in this context so use true to be conservative */
4389 if (check_input_parameters(sample_rate, format, channel_count,
4390 true /*is_usb_hifi */) != 0)
4391 return 0;
4392
4393 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4394 sample_rate,
4395 format,
4396 channel_count,
4397 is_low_latency);
4398}
4399
Derek Chenf6318be2017-06-12 17:16:24 -04004400size_t get_output_period_size(uint32_t sample_rate,
4401 audio_format_t format,
4402 int channel_count,
4403 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304404{
4405 size_t size = 0;
4406 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4407
4408 if ((duration == 0) || (sample_rate == 0) ||
4409 (bytes_per_sample == 0) || (channel_count == 0)) {
4410 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4411 bytes_per_sample, channel_count);
4412 return -EINVAL;
4413 }
4414
4415 size = (sample_rate *
4416 duration *
4417 bytes_per_sample *
4418 channel_count) / 1000;
4419 /*
4420 * To have same PCM samples for all channels, the buffer size requires to
4421 * be multiple of (number of channels * bytes per sample)
4422 * For writes to succeed, the buffer must be written at address which is multiple of 32
4423 */
4424 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4425
4426 return (size/(channel_count * bytes_per_sample));
4427}
4428
Zhou Song48453a02018-01-10 17:50:59 +08004429static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304430{
4431 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004432 uint64_t written_frames = 0;
4433 uint64_t kernel_frames = 0;
4434 uint64_t dsp_frames = 0;
4435 uint64_t signed_frames = 0;
4436 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304437
4438 /* This adjustment accounts for buffering after app processor.
4439 * It is based on estimated DSP latency per use case, rather than exact.
4440 */
George Gao9ba8a142020-07-23 14:30:03 -07004441 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004442 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304443
Zhou Song48453a02018-01-10 17:50:59 +08004444 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004445 written_frames = out->written /
4446 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4447
Ashish Jain5106d362016-05-11 19:23:33 +05304448 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4449 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4450 * hence only estimate.
4451 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004452 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4453 kernel_frames = kernel_buffer_size /
4454 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304455
Weiyin Jiang4813da12020-05-28 00:37:28 +08004456 if (written_frames >= (kernel_frames + dsp_frames))
4457 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304458
Zhou Song48453a02018-01-10 17:50:59 +08004459 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304460 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004461 if (timestamp != NULL )
4462 *timestamp = out->writeAt;
4463 } else if (timestamp != NULL) {
4464 clock_gettime(CLOCK_MONOTONIC, timestamp);
4465 }
4466 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304467
Weiyin Jiang4813da12020-05-28 00:37:28 +08004468 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4469 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304470
4471 return actual_frames_rendered;
4472}
4473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4475{
4476 struct stream_out *out = (struct stream_out *)stream;
4477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004478 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479}
4480
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004481static int out_set_sample_rate(struct audio_stream *stream __unused,
4482 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483{
4484 return -ENOSYS;
4485}
4486
4487static size_t out_get_buffer_size(const struct audio_stream *stream)
4488{
4489 struct stream_out *out = (struct stream_out *)stream;
4490
Varun Balaraje49253e2017-07-06 19:48:56 +05304491 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304492 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304493 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304494 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4495 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4496 else
4497 return out->compr_config.fragment_size;
4498 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004499 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304500 else if (is_offload_usecase(out->usecase) &&
4501 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304502 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004503
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004504 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004505 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506}
4507
4508static uint32_t out_get_channels(const struct audio_stream *stream)
4509{
4510 struct stream_out *out = (struct stream_out *)stream;
4511
4512 return out->channel_mask;
4513}
4514
4515static audio_format_t out_get_format(const struct audio_stream *stream)
4516{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004517 struct stream_out *out = (struct stream_out *)stream;
4518
4519 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520}
4521
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004522static int out_set_format(struct audio_stream *stream __unused,
4523 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524{
4525 return -ENOSYS;
4526}
4527
4528static int out_standby(struct audio_stream *stream)
4529{
4530 struct stream_out *out = (struct stream_out *)stream;
4531 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004532 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004533
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304534 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4535 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004536
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004537 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004539 if (adev->adm_deregister_stream)
4540 adev->adm_deregister_stream(adev->adm_data, out->handle);
4541
Weiyin Jiang280ea742020-09-08 20:28:22 +08004542 if (is_offload_usecase(out->usecase)) {
4543 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004544 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004545 pthread_mutex_unlock(&out->latch_lock);
4546 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004547
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004548 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004550 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4551 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304552 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004553 pthread_mutex_unlock(&adev->lock);
4554 pthread_mutex_unlock(&out->lock);
4555 ALOGD("VOIP output entered standby");
4556 return 0;
4557 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004558 if (out->pcm) {
4559 pcm_close(out->pcm);
4560 out->pcm = NULL;
4561 }
Meng Wanga09da002020-04-20 12:56:04 +08004562 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4563 if (adev->haptic_pcm) {
4564 pcm_close(adev->haptic_pcm);
4565 adev->haptic_pcm = NULL;
4566 }
4567
4568 if (adev->haptic_buffer != NULL) {
4569 free(adev->haptic_buffer);
4570 adev->haptic_buffer = NULL;
4571 adev->haptic_buffer_size = 0;
4572 }
4573 adev->haptic_pcm_device_id = 0;
4574 }
4575
Haynes Mathew George16081042017-05-31 17:16:49 -07004576 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4577 do_stop = out->playback_started;
4578 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004579
4580 if (out->mmap_shared_memory_fd >= 0) {
4581 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4582 __func__, out->mmap_shared_memory_fd);
4583 close(out->mmap_shared_memory_fd);
4584 out->mmap_shared_memory_fd = -1;
4585 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004586 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004587 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004588 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304589 out->send_next_track_params = false;
4590 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004591 out->gapless_mdata.encoder_delay = 0;
4592 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004593 if (out->compr != NULL) {
4594 compress_close(out->compr);
4595 out->compr = NULL;
4596 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004597 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004598 if (do_stop) {
4599 stop_output_stream(out);
4600 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304601 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004602 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004603 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 }
4605 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004606 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 return 0;
4608}
4609
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304610static int out_on_error(struct audio_stream *stream)
4611{
4612 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004613 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304614
4615 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004616 // always send CMD_ERROR for offload streams, this
4617 // is needed e.g. when SSR happens within compress_open
4618 // since the stream is active, offload_callback_thread is also active.
4619 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08004620 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004621 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004622 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004623 }
4624 pthread_mutex_unlock(&out->lock);
4625
4626 status = out_standby(&out->stream.common);
4627
4628 lock_output_stream(out);
4629 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004630 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304631 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304632
4633 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4634 ALOGD("Setting previous card status if offline");
4635 out->prev_card_status_offline = true;
4636 }
4637
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304638 pthread_mutex_unlock(&out->lock);
4639
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004640 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304641}
4642
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304643/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004644 * standby implementation without locks, assumes that the callee already
4645 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304646 */
4647int out_standby_l(struct audio_stream *stream)
4648{
4649 struct stream_out *out = (struct stream_out *)stream;
4650 struct audio_device *adev = out->dev;
4651
4652 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4653 stream, out->usecase, use_case_table[out->usecase]);
4654
4655 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004656 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304657 if (adev->adm_deregister_stream)
4658 adev->adm_deregister_stream(adev->adm_data, out->handle);
4659
Weiyin Jiang280ea742020-09-08 20:28:22 +08004660 if (is_offload_usecase(out->usecase)) {
4661 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304662 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004663 pthread_mutex_unlock(&out->latch_lock);
4664 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304665
4666 out->standby = true;
4667 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4668 voice_extn_compress_voip_close_output_stream(stream);
4669 out->started = 0;
4670 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004671 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304672 return 0;
4673 } else if (!is_offload_usecase(out->usecase)) {
4674 if (out->pcm) {
4675 pcm_close(out->pcm);
4676 out->pcm = NULL;
4677 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004678 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4679 if (adev->haptic_pcm) {
4680 pcm_close(adev->haptic_pcm);
4681 adev->haptic_pcm = NULL;
4682 }
4683
4684 if (adev->haptic_buffer != NULL) {
4685 free(adev->haptic_buffer);
4686 adev->haptic_buffer = NULL;
4687 adev->haptic_buffer_size = 0;
4688 }
4689 adev->haptic_pcm_device_id = 0;
4690 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304691 } else {
4692 ALOGD("copl(%p):standby", out);
4693 out->send_next_track_params = false;
4694 out->is_compr_metadata_avail = false;
4695 out->gapless_mdata.encoder_delay = 0;
4696 out->gapless_mdata.encoder_padding = 0;
4697 if (out->compr != NULL) {
4698 compress_close(out->compr);
4699 out->compr = NULL;
4700 }
4701 }
4702 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004703 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304704 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004705 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304706 return 0;
4707}
4708
Aalique Grahame22e49102018-12-18 14:23:57 -08004709static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710{
Aalique Grahame22e49102018-12-18 14:23:57 -08004711 struct stream_out *out = (struct stream_out *)stream;
4712
4713 // We try to get the lock for consistency,
4714 // but it isn't necessary for these variables.
4715 // If we're not in standby, we may be blocked on a write.
4716 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4717 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4718 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4719
Andy Hunga1f48fa2019-07-01 18:14:53 -07004720 char buffer[256]; // for statistics formatting
4721 if (!is_offload_usecase(out->usecase)) {
4722 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4723 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4724 }
4725
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004726 if (out->start_latency_ms.n > 0) {
4727 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4728 dprintf(fd, " Start latency ms: %s\n", buffer);
4729 }
4730
Aalique Grahame22e49102018-12-18 14:23:57 -08004731 if (locked) {
4732 pthread_mutex_unlock(&out->lock);
4733 }
4734
4735 // dump error info
4736 (void)error_log_dump(
4737 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739 return 0;
4740}
4741
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004742static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4743{
4744 int ret = 0;
4745 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004746
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004747 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004748 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004749 return -EINVAL;
4750 }
4751
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304752 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004753
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004754 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4755 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304756 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004757 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004758 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4759 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304760 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004761 }
4762
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004763 ALOGV("%s new encoder delay %u and padding %u", __func__,
4764 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4765
4766 return 0;
4767}
4768
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004769static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4770{
4771 return out == adev->primary_output || out == adev->voice_tx_output;
4772}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004773
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304774// note: this call is safe only if the stream_cb is
4775// removed first in close_output_stream (as is done now).
4776static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4777{
4778 if (!stream || !parms)
4779 return;
4780
4781 struct stream_out *out = (struct stream_out *)stream;
4782 struct audio_device *adev = out->dev;
4783
4784 card_status_t status;
4785 int card;
4786 if (parse_snd_card_status(parms, &card, &status) < 0)
4787 return;
4788
4789 pthread_mutex_lock(&adev->lock);
4790 bool valid_cb = (card == adev->snd_card);
4791 pthread_mutex_unlock(&adev->lock);
4792
4793 if (!valid_cb)
4794 return;
4795
4796 lock_output_stream(out);
4797 if (out->card_status != status)
4798 out->card_status = status;
4799 pthread_mutex_unlock(&out->lock);
4800
4801 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4802 use_case_table[out->usecase],
4803 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4804
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304805 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304806 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304807 if (voice_is_call_state_active(adev) &&
4808 out == adev->primary_output) {
4809 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4810 pthread_mutex_lock(&adev->lock);
4811 voice_stop_call(adev);
4812 adev->mode = AUDIO_MODE_NORMAL;
4813 pthread_mutex_unlock(&adev->lock);
4814 }
4815 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304816 return;
4817}
4818
Kevin Rocardfce19002017-08-07 19:21:36 -07004819static int get_alive_usb_card(struct str_parms* parms) {
4820 int card;
4821 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4822 !audio_extn_usb_alive(card)) {
4823 return card;
4824 }
4825 return -ENODEV;
4826}
4827
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004828int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004829 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004830{
4831 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004833 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004834 bool bypass_a2dp = false;
4835 bool reconfig = false;
4836 unsigned long service_interval = 0;
4837
4838 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004839 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4840
4841 list_init(&new_devices);
4842 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004843
4844 lock_output_stream(out);
4845 pthread_mutex_lock(&adev->lock);
4846
4847 /*
4848 * When HDMI cable is unplugged the music playback is paused and
4849 * the policy manager sends routing=0. But the audioflinger continues
4850 * to write data until standby time (3sec). As the HDMI core is
4851 * turned off, the write gets blocked.
4852 * Avoid this by routing audio to speaker until standby.
4853 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004854 if (is_single_device_type_equal(&out->device_list,
4855 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004856 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857 !audio_extn_passthru_is_passthrough_stream(out) &&
4858 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004859 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004860 }
4861 /*
4862 * When A2DP is disconnected the
4863 * music playback is paused and the policy manager sends routing=0
4864 * But the audioflinger continues to write data until standby time
4865 * (3sec). As BT is turned off, the write gets blocked.
4866 * Avoid this by routing audio to speaker until standby.
4867 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004868 if (is_a2dp_out_device_type(&out->device_list) &&
4869 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870 !audio_extn_a2dp_source_is_ready() &&
4871 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004872 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004873 }
4874 /*
4875 * When USB headset is disconnected the music platback paused
4876 * and the policy manager send routing=0. But if the USB is connected
4877 * back before the standby time, AFE is not closed and opened
4878 * when USB is connected back. So routing to speker will guarantee
4879 * AFE reconfiguration and AFE will be opend once USB is connected again
4880 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004881 if (is_usb_out_device_type(&out->device_list) &&
4882 list_empty(&new_devices) &&
4883 !audio_extn_usb_connected(NULL)) {
4884 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4885 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004886 /* To avoid a2dp to sco overlapping / BT device improper state
4887 * check with BT lib about a2dp streaming support before routing
4888 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004889 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004890 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004891 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4892 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004893 //combo usecase just by pass a2dp
4894 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4895 bypass_a2dp = true;
4896 } else {
4897 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4898 /* update device to a2dp and don't route as BT returned error
4899 * However it is still possible a2dp routing called because
4900 * of current active device disconnection (like wired headset)
4901 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004902 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004903 pthread_mutex_unlock(&adev->lock);
4904 pthread_mutex_unlock(&out->lock);
4905 goto error;
4906 }
4907 }
4908 }
4909
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004910 // Workaround: If routing to an non existing usb device, fail gracefully
4911 // The routing request will otherwise block during 10 second
4912 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004913 if (is_usb_out_device_type(&new_devices)) {
4914 struct str_parms *parms =
4915 str_parms_create_str(get_usb_device_address(&new_devices));
4916 if (!parms)
4917 goto error;
4918 if ((card = get_alive_usb_card(parms)) >= 0) {
4919 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4920 pthread_mutex_unlock(&adev->lock);
4921 pthread_mutex_unlock(&out->lock);
4922 str_parms_destroy(parms);
4923 ret = -ENOSYS;
4924 goto error;
4925 }
4926 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004927 }
4928
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004929 // Workaround: If routing to an non existing hdmi device, fail gracefully
4930 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4931 (platform_get_edid_info_v2(adev->platform,
4932 out->extconn.cs.controller,
4933 out->extconn.cs.stream) != 0)) {
4934 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4935 pthread_mutex_unlock(&adev->lock);
4936 pthread_mutex_unlock(&out->lock);
4937 ret = -ENOSYS;
4938 goto error;
4939 }
4940
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004941 /*
4942 * select_devices() call below switches all the usecases on the same
4943 * backend to the new device. Refer to check_usecases_codec_backend() in
4944 * the select_devices(). But how do we undo this?
4945 *
4946 * For example, music playback is active on headset (deep-buffer usecase)
4947 * and if we go to ringtones and select a ringtone, low-latency usecase
4948 * will be started on headset+speaker. As we can't enable headset+speaker
4949 * and headset devices at the same time, select_devices() switches the music
4950 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4951 * So when the ringtone playback is completed, how do we undo the same?
4952 *
4953 * We are relying on the out_set_parameters() call on deep-buffer output,
4954 * once the ringtone playback is ended.
4955 * NOTE: We should not check if the current devices are same as new devices.
4956 * Because select_devices() must be called to switch back the music
4957 * playback to headset.
4958 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004959 if (!list_empty(&new_devices)) {
4960 bool same_dev = compare_devices(&out->device_list, &new_devices);
4961 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004962
4963 if (output_drives_call(adev, out)) {
4964 if (!voice_is_call_state_active(adev)) {
4965 if (adev->mode == AUDIO_MODE_IN_CALL) {
4966 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004967 ret = voice_start_call(adev);
4968 }
4969 } else {
4970 adev->current_call_output = out;
4971 voice_update_devices_for_all_voice_usecases(adev);
4972 }
4973 }
4974
Mingshu Pang971ff702020-09-09 15:28:22 +08004975 if (is_usb_out_device_type(&out->device_list)) {
4976 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4977 audio_extn_usb_set_service_interval(true /*playback*/,
4978 service_interval,
4979 &reconfig);
4980 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4981 }
4982
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004983 if (!out->standby) {
4984 if (!same_dev) {
4985 ALOGV("update routing change");
4986 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4987 adev->perf_lock_opts,
4988 adev->perf_lock_opts_size);
4989 if (adev->adm_on_routing_change)
4990 adev->adm_on_routing_change(adev->adm_data,
4991 out->handle);
4992 }
4993 if (!bypass_a2dp) {
4994 select_devices(adev, out->usecase);
4995 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004996 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4997 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004998 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004999 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005000 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005001 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005002 }
5003
5004 if (!same_dev) {
5005 // on device switch force swap, lower functions will make sure
5006 // to check if swap is allowed or not.
5007 platform_set_swap_channels(adev, true);
5008 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5009 }
5010 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005011 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005012 pthread_mutex_lock(&out->latch_lock);
5013 if (out->a2dp_compress_mute) {
5014 out->a2dp_compress_mute = false;
5015 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5016 }
5017 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005018 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
5019 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5020 }
5021 }
5022 }
5023
5024 pthread_mutex_unlock(&adev->lock);
5025 pthread_mutex_unlock(&out->lock);
5026
5027 /*handles device and call state changes*/
5028 audio_extn_extspk_update(adev->extspk);
5029
5030error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005031 ALOGV("%s: exit: code(%d)", __func__, ret);
5032 return ret;
5033}
5034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005035static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5036{
5037 struct stream_out *out = (struct stream_out *)stream;
5038 struct audio_device *adev = out->dev;
5039 struct str_parms *parms;
5040 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005041 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005042 int ext_controller = -1;
5043 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044
sangwoobc677242013-08-08 16:53:43 +09005045 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005046 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305048 if (!parms)
5049 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005050
5051 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5052 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005053 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005054 out->extconn.cs.controller = ext_controller;
5055 out->extconn.cs.stream = ext_stream;
5056 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5057 use_case_table[out->usecase], out->extconn.cs.controller,
5058 out->extconn.cs.stream);
5059 }
5060
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005061 if (out == adev->primary_output) {
5062 pthread_mutex_lock(&adev->lock);
5063 audio_extn_set_parameters(adev, parms);
5064 pthread_mutex_unlock(&adev->lock);
5065 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005066 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005067 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005068 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005069
5070 audio_extn_dts_create_state_notifier_node(out->usecase);
5071 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5072 popcount(out->channel_mask),
5073 out->playback_started);
5074
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005075 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005076 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005077
Surendar Karkaf51b5842018-04-26 11:28:38 +05305078 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5079 sizeof(value));
5080 if (err >= 0) {
5081 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5082 audio_extn_send_dual_mono_mixing_coefficients(out);
5083 }
5084
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305085 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5086 if (err >= 0) {
5087 strlcpy(out->profile, value, sizeof(out->profile));
5088 ALOGV("updating stream profile with value '%s'", out->profile);
5089 lock_output_stream(out);
5090 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5091 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005092 &out->device_list, out->flags,
5093 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305094 out->sample_rate, out->bit_width,
5095 out->channel_mask, out->profile,
5096 &out->app_type_cfg);
5097 pthread_mutex_unlock(&out->lock);
5098 }
5099
Alexy Joseph98988832017-01-13 14:56:59 -08005100 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005101 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5102 // and vendor.audio.hal.output.suspend.supported is set to true
5103 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005104 //check suspend parameter only for low latency and if the property
5105 //is enabled
5106 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5107 ALOGI("%s: got suspend_playback %s", __func__, value);
5108 lock_output_stream(out);
5109 if (!strncmp(value, "false", 5)) {
5110 //suspend_playback=false is supposed to set QOS value back to 75%
5111 //the mixer control sent with value Enable will achieve that
5112 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5113 } else if (!strncmp (value, "true", 4)) {
5114 //suspend_playback=true is supposed to remove QOS value
5115 //resetting the mixer control will set the default value
5116 //for the mixer control which is Disable and this removes the QOS vote
5117 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5118 } else {
5119 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5120 " got %s", __func__, value);
5121 ret = -1;
5122 }
5123
5124 if (ret != 0) {
5125 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5126 __func__, out->pm_qos_mixer_path, ret);
5127 }
5128
5129 pthread_mutex_unlock(&out->lock);
5130 }
5131 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005132
Alexy Joseph98988832017-01-13 14:56:59 -08005133 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305135error:
Eric Laurent994a6932013-07-17 11:51:42 -07005136 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 return ret;
5138}
5139
Paul McLeana50b7332018-12-17 08:24:21 -07005140static int in_set_microphone_direction(const struct audio_stream_in *stream,
5141 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005142 struct stream_in *in = (struct stream_in *)stream;
5143
5144 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5145
5146 in->direction = dir;
5147
5148 if (in->standby)
5149 return 0;
5150
5151 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005152}
5153
5154static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005155 struct stream_in *in = (struct stream_in *)stream;
5156
5157 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5158
5159 if (zoom > 1.0 || zoom < -1.0)
5160 return -EINVAL;
5161
5162 in->zoom = zoom;
5163
5164 if (in->standby)
5165 return 0;
5166
5167 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005168}
5169
5170
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005171static bool stream_get_parameter_channels(struct str_parms *query,
5172 struct str_parms *reply,
5173 audio_channel_mask_t *supported_channel_masks) {
5174 int ret = -1;
5175 char value[512];
5176 bool first = true;
5177 size_t i, j;
5178
5179 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5180 ret = 0;
5181 value[0] = '\0';
5182 i = 0;
5183 while (supported_channel_masks[i] != 0) {
5184 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5185 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5186 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305187 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005188
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305189 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005190 first = false;
5191 break;
5192 }
5193 }
5194 i++;
5195 }
5196 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5197 }
5198 return ret == 0;
5199}
5200
5201static bool stream_get_parameter_formats(struct str_parms *query,
5202 struct str_parms *reply,
5203 audio_format_t *supported_formats) {
5204 int ret = -1;
5205 char value[256];
5206 size_t i, j;
5207 bool first = true;
5208
5209 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5210 ret = 0;
5211 value[0] = '\0';
5212 i = 0;
5213 while (supported_formats[i] != 0) {
5214 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5215 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5216 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305217 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005218 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305219 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005220 first = false;
5221 break;
5222 }
5223 }
5224 i++;
5225 }
5226 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5227 }
5228 return ret == 0;
5229}
5230
5231static bool stream_get_parameter_rates(struct str_parms *query,
5232 struct str_parms *reply,
5233 uint32_t *supported_sample_rates) {
5234
5235 int i;
5236 char value[256];
5237 int ret = -1;
5238 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5239 ret = 0;
5240 value[0] = '\0';
5241 i=0;
5242 int cursor = 0;
5243 while (supported_sample_rates[i]) {
5244 int avail = sizeof(value) - cursor;
5245 ret = snprintf(value + cursor, avail, "%s%d",
5246 cursor > 0 ? "|" : "",
5247 supported_sample_rates[i]);
5248 if (ret < 0 || ret >= avail) {
5249 // if cursor is at the last element of the array
5250 // overwrite with \0 is duplicate work as
5251 // snprintf already put a \0 in place.
5252 // else
5253 // we had space to write the '|' at value[cursor]
5254 // (which will be overwritten) or no space to fill
5255 // the first element (=> cursor == 0)
5256 value[cursor] = '\0';
5257 break;
5258 }
5259 cursor += ret;
5260 ++i;
5261 }
5262 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5263 value);
5264 }
5265 return ret >= 0;
5266}
5267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5269{
5270 struct stream_out *out = (struct stream_out *)stream;
5271 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005272 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005273 char value[256];
5274 struct str_parms *reply = str_parms_create();
5275 size_t i, j;
5276 int ret;
5277 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005278
5279 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005280 if (reply) {
5281 str_parms_destroy(reply);
5282 }
5283 if (query) {
5284 str_parms_destroy(query);
5285 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005286 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5287 return NULL;
5288 }
5289
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005290 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5292 if (ret >= 0) {
5293 value[0] = '\0';
5294 i = 0;
5295 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005296 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5297 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005298 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005299 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005301 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 first = false;
5303 break;
5304 }
5305 }
5306 i++;
5307 }
5308 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5309 str = str_parms_to_str(reply);
5310 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005311 voice_extn_out_get_parameters(out, query, reply);
5312 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005313 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005314
Alexy Joseph62142aa2015-11-16 15:10:34 -08005315
5316 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5317 if (ret >= 0) {
5318 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305319 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5320 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005321 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305322 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005323 } else {
5324 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305325 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005326 }
5327 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005328 if (str)
5329 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005330 str = str_parms_to_str(reply);
5331 }
5332
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005333 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5334 if (ret >= 0) {
5335 value[0] = '\0';
5336 i = 0;
5337 first = true;
5338 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005339 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5340 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005341 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005342 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005343 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005344 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005345 first = false;
5346 break;
5347 }
5348 }
5349 i++;
5350 }
5351 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005352 if (str)
5353 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005354 str = str_parms_to_str(reply);
5355 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005356
5357 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5358 if (ret >= 0) {
5359 value[0] = '\0';
5360 i = 0;
5361 first = true;
5362 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005363 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5364 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005365 if (!first) {
5366 strlcat(value, "|", sizeof(value));
5367 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005368 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005369 first = false;
5370 break;
5371 }
5372 }
5373 i++;
5374 }
5375 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5376 if (str)
5377 free(str);
5378 str = str_parms_to_str(reply);
5379 }
5380
Alexy Joseph98988832017-01-13 14:56:59 -08005381 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5382 //only low latency track supports suspend_resume
5383 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005384 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005385 if (str)
5386 free(str);
5387 str = str_parms_to_str(reply);
5388 }
5389
5390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005391 str_parms_destroy(query);
5392 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005393 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005394 return str;
5395}
5396
5397static uint32_t out_get_latency(const struct audio_stream_out *stream)
5398{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005399 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005401 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402
Alexy Josephaa54c872014-12-03 02:46:47 -08005403 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305404 lock_output_stream(out);
5405 latency = audio_extn_utils_compress_get_dsp_latency(out);
5406 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005407 } else if ((out->realtime) ||
5408 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005409 // since the buffer won't be filled up faster than realtime,
5410 // return a smaller number
5411 if (out->config.rate)
5412 period_ms = (out->af_period_multiplier * out->config.period_size *
5413 1000) / (out->config.rate);
5414 else
5415 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005416 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005417 } else {
5418 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005419 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005420 }
5421
Zhou Songd2537a02020-06-11 22:04:46 +08005422 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005423 latency += audio_extn_a2dp_get_encoder_latency();
5424
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305425 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005426 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005427}
5428
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305429static float AmpToDb(float amplification)
5430{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305431 float db = DSD_VOLUME_MIN_DB;
5432 if (amplification > 0) {
5433 db = 20 * log10(amplification);
5434 if(db < DSD_VOLUME_MIN_DB)
5435 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305436 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305437 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305438}
5439
Arun Mirpuri5d170872019-03-26 13:21:31 -07005440static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5441 float right)
5442{
5443 struct stream_out *out = (struct stream_out *)stream;
5444 long volume = 0;
5445 char mixer_ctl_name[128] = "";
5446 struct audio_device *adev = out->dev;
5447 struct mixer_ctl *ctl = NULL;
5448 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5449 PCM_PLAYBACK);
5450
5451 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5452 "Playback %d Volume", pcm_device_id);
5453 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5454 if (!ctl) {
5455 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5456 __func__, mixer_ctl_name);
5457 return -EINVAL;
5458 }
5459 if (left != right)
5460 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5461 __func__, left, right);
5462 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5463 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5464 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5465 __func__, mixer_ctl_name, volume);
5466 return -EINVAL;
5467 }
5468 return 0;
5469}
5470
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305471static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5472 float right)
5473{
5474 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305475 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305476 char mixer_ctl_name[128];
5477 struct audio_device *adev = out->dev;
5478 struct mixer_ctl *ctl;
5479 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5480 PCM_PLAYBACK);
5481
5482 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5483 "Compress Playback %d Volume", pcm_device_id);
5484 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5485 if (!ctl) {
5486 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5487 __func__, mixer_ctl_name);
5488 return -EINVAL;
5489 }
5490 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5491 __func__, mixer_ctl_name, left, right);
5492 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5493 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5494 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5495
5496 return 0;
5497}
5498
Zhou Song2b8f28f2017-09-11 10:51:38 +08005499static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5500 float right)
5501{
5502 struct stream_out *out = (struct stream_out *)stream;
5503 char mixer_ctl_name[] = "App Type Gain";
5504 struct audio_device *adev = out->dev;
5505 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305506 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005507
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005508 if (!is_valid_volume(left, right)) {
5509 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5510 __func__, left, right);
5511 return -EINVAL;
5512 }
5513
Zhou Song2b8f28f2017-09-11 10:51:38 +08005514 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5515 if (!ctl) {
5516 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5517 __func__, mixer_ctl_name);
5518 return -EINVAL;
5519 }
5520
5521 set_values[0] = 0; //0: Rx Session 1:Tx Session
5522 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305523 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5524 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005525
5526 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5527 return 0;
5528}
5529
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305530static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5531 float right)
5532{
5533 struct stream_out *out = (struct stream_out *)stream;
5534 /* Volume control for pcm playback */
5535 if (left != right) {
5536 return -EINVAL;
5537 } else {
5538 char mixer_ctl_name[128];
5539 struct audio_device *adev = out->dev;
5540 struct mixer_ctl *ctl;
5541 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5542 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5543 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5544 if (!ctl) {
5545 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5546 return -EINVAL;
5547 }
5548
5549 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5550 int ret = mixer_ctl_set_value(ctl, 0, volume);
5551 if (ret < 0) {
5552 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5553 return -EINVAL;
5554 }
5555
5556 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5557
5558 return 0;
5559 }
5560}
5561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005562static int out_set_volume(struct audio_stream_out *stream, float left,
5563 float right)
5564{
Eric Laurenta9024de2013-04-04 09:19:12 -07005565 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005566 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305567 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005568
Arun Mirpuri5d170872019-03-26 13:21:31 -07005569 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005570 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5571 /* only take left channel into account: the API is for stereo anyway */
Weiyin Jiang280ea742020-09-08 20:28:22 +08005572 pthread_mutex_lock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005573 out->muted = (left == 0.0f);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005574 pthread_mutex_unlock(&out->latch_lock);
Eric Laurenta9024de2013-04-04 09:19:12 -07005575 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005576 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305577 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005578 /*
5579 * Set mute or umute on HDMI passthrough stream.
5580 * Only take left channel into account.
5581 * Mute is 0 and unmute 1
5582 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305583 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305584 } else if (out->format == AUDIO_FORMAT_DSD){
5585 char mixer_ctl_name[128] = "DSD Volume";
5586 struct audio_device *adev = out->dev;
5587 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5588
5589 if (!ctl) {
5590 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5591 __func__, mixer_ctl_name);
5592 return -EINVAL;
5593 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305594 volume[0] = (long)(AmpToDb(left));
5595 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305596 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5597 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005598 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005599 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005600 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5601 struct listnode *node = NULL;
5602 list_for_each(node, &adev->active_outputs_list) {
5603 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5604 streams_output_ctxt_t,
5605 list);
5606 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5607 out->volume_l = out_ctxt->output->volume_l;
5608 out->volume_r = out_ctxt->output->volume_r;
5609 }
5610 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005611 pthread_mutex_lock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005612 if (!out->a2dp_compress_mute) {
5613 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5614 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005615 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005616 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005617 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005618 pthread_mutex_lock(&out->latch_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005619 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305620 if (!out->a2dp_compress_mute)
5621 ret = out_set_compr_volume(stream, left, right);
5622 out->volume_l = left;
5623 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005624 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305625 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005626 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005627 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005628 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5629 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5630 if (!out->standby) {
5631 audio_extn_utils_send_app_type_gain(out->dev,
5632 out->app_type_cfg.app_type,
5633 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005634 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005635 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005636 out->volume_l = left;
5637 out->volume_r = right;
5638 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005639 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5640 ALOGV("%s: MMAP set volume called", __func__);
5641 if (!out->standby)
5642 ret = out_set_mmap_volume(stream, left, right);
5643 out->volume_l = left;
5644 out->volume_r = right;
5645 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305646 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305647 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5648 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305649 /* Volume control for pcm playback */
5650 if (!out->standby)
5651 ret = out_set_pcm_volume(stream, left, right);
5652 else
5653 out->apply_volume = true;
5654
5655 out->volume_l = left;
5656 out->volume_r = right;
5657 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005658 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5659 ALOGV("%s: bus device set volume called", __func__);
5660 if (!out->standby)
5661 ret = out_set_pcm_volume(stream, left, right);
5662 out->volume_l = left;
5663 out->volume_r = right;
5664 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005665 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 return -ENOSYS;
5668}
5669
Zhou Songc9672822017-08-16 16:01:39 +08005670static void update_frames_written(struct stream_out *out, size_t bytes)
5671{
5672 size_t bpf = 0;
5673
5674 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5675 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5676 bpf = 1;
5677 else if (!is_offload_usecase(out->usecase))
5678 bpf = audio_bytes_per_sample(out->format) *
5679 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005680
5681 pthread_mutex_lock(&out->position_query_lock);
5682 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005683 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005684 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5685 }
5686 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005687}
5688
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005689int split_and_write_audio_haptic_data(struct stream_out *out,
5690 const void *buffer, size_t bytes_to_write)
5691{
5692 struct audio_device *adev = out->dev;
5693
5694 int ret = 0;
5695 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5696 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5697 size_t frame_size = channel_count * bytes_per_sample;
5698 size_t frame_count = bytes_to_write / frame_size;
5699
5700 bool force_haptic_path =
5701 property_get_bool("vendor.audio.test_haptic", false);
5702
5703 // extract Haptics data from Audio buffer
5704 bool alloc_haptic_buffer = false;
5705 int haptic_channel_count = adev->haptics_config.channels;
5706 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5707 size_t audio_frame_size = frame_size - haptic_frame_size;
5708 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5709
5710 if (adev->haptic_buffer == NULL) {
5711 alloc_haptic_buffer = true;
5712 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5713 free(adev->haptic_buffer);
5714 adev->haptic_buffer_size = 0;
5715 alloc_haptic_buffer = true;
5716 }
5717
5718 if (alloc_haptic_buffer) {
5719 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005720 if(adev->haptic_buffer == NULL) {
5721 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5722 return -ENOMEM;
5723 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005724 adev->haptic_buffer_size = total_haptic_buffer_size;
5725 }
5726
5727 size_t src_index = 0, aud_index = 0, hap_index = 0;
5728 uint8_t *audio_buffer = (uint8_t *)buffer;
5729 uint8_t *haptic_buffer = adev->haptic_buffer;
5730
5731 // This is required for testing only. This works for stereo data only.
5732 // One channel is fed to audio stream and other to haptic stream for testing.
5733 if (force_haptic_path)
5734 audio_frame_size = haptic_frame_size = bytes_per_sample;
5735
5736 for (size_t i = 0; i < frame_count; i++) {
5737 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5738 audio_frame_size);
5739 aud_index += audio_frame_size;
5740 src_index += audio_frame_size;
5741
5742 if (adev->haptic_pcm)
5743 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5744 haptic_frame_size);
5745 hap_index += haptic_frame_size;
5746 src_index += haptic_frame_size;
5747
5748 // This is required for testing only.
5749 // Discard haptic channel data.
5750 if (force_haptic_path)
5751 src_index += haptic_frame_size;
5752 }
5753
5754 // write to audio pipeline
5755 ret = pcm_write(out->pcm, (void *)audio_buffer,
5756 frame_count * audio_frame_size);
5757
5758 // write to haptics pipeline
5759 if (adev->haptic_pcm)
5760 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5761 frame_count * haptic_frame_size);
5762
5763 return ret;
5764}
5765
Aalique Grahame22e49102018-12-18 14:23:57 -08005766#ifdef NO_AUDIO_OUT
5767static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5768 const void *buffer __unused, size_t bytes)
5769{
5770 struct stream_out *out = (struct stream_out *)stream;
5771
5772 /* No Output device supported other than BT for playback.
5773 * Sleep for the amount of buffer duration
5774 */
5775 lock_output_stream(out);
5776 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5777 (const struct audio_stream_out *)&out->stream) /
5778 out_get_sample_rate(&out->stream.common));
5779 pthread_mutex_unlock(&out->lock);
5780 return bytes;
5781}
5782#endif
5783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005784static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5785 size_t bytes)
5786{
5787 struct stream_out *out = (struct stream_out *)stream;
5788 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005789 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305790 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005791 const size_t frame_size = audio_stream_out_frame_size(stream);
5792 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305793 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005794 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005795
Haynes Mathew George380745d2017-10-04 15:27:45 -07005796 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005797 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305798
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305799 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005800
Dhananjay Kumarac341582017-02-23 23:42:25 +05305801 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305802 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305803 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5804 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005805 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305806 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305807 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305808 ALOGD(" %s: sound card is not active/SSR state", __func__);
5809 ret= -EIO;
5810 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305811 }
5812 }
5813
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305814 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305815 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305816 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305817 goto exit;
5818 }
5819
Haynes Mathew George16081042017-05-31 17:16:49 -07005820 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5821 ret = -EINVAL;
5822 goto exit;
5823 }
5824
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005825 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305826 !out->is_iec61937_info_available) {
5827
5828 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5829 out->is_iec61937_info_available = true;
5830 } else if (audio_extn_passthru_is_enabled()) {
5831 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305832 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305833
5834 if((out->format == AUDIO_FORMAT_DTS) ||
5835 (out->format == AUDIO_FORMAT_DTS_HD)) {
5836 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5837 buffer, bytes);
5838 if (ret) {
5839 if (ret != -ENOSYS) {
5840 out->is_iec61937_info_available = false;
5841 ALOGD("iec61937 transmission info not yet updated retry");
5842 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305843 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305844 /* if stream has started and after that there is
5845 * stream config change (iec transmission config)
5846 * then trigger select_device to update backend configuration.
5847 */
5848 out->stream_config_changed = true;
5849 pthread_mutex_lock(&adev->lock);
5850 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305851 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005852 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305853 ret = -EINVAL;
5854 goto exit;
5855 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305856 pthread_mutex_unlock(&adev->lock);
5857 out->stream_config_changed = false;
5858 out->is_iec61937_info_available = true;
5859 }
5860 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305861
Meng Wang4c32fb42020-01-16 17:57:11 +08005862#ifdef AUDIO_GKI_ENABLED
5863 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5864 compr_passthr = out->compr_config.codec->reserved[0];
5865#else
5866 compr_passthr = out->compr_config.codec->compr_passthr;
5867#endif
5868
Garmond Leung317cbf12017-09-13 16:20:50 -07005869 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005870 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305871 (out->is_iec61937_info_available == true)) {
5872 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5873 ret = -EINVAL;
5874 goto exit;
5875 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305876 }
5877 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305878
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005879 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005880 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005881 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5882 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305883 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305884 ret = -EIO;
5885 goto exit;
5886 }
5887 }
5888 }
5889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005890 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005891 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005892 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5893
Eric Laurent150dbfe2013-02-27 14:31:02 -08005894 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005895 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5896 ret = voice_extn_compress_voip_start_output_stream(out);
5897 else
5898 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005899 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005901 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005902 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005903 goto exit;
5904 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305905 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005906 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005907
5908 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005909 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005910 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305911 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005912 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005913 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305914
5915 if ((out->is_iec61937_info_available == true) &&
5916 (audio_extn_passthru_is_passthrough_stream(out))&&
5917 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5918 ret = -EINVAL;
5919 goto exit;
5920 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305921 if (out->set_dual_mono)
5922 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005923
5924 // log startup time in ms.
5925 simple_stats_log(
5926 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005927 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005928
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005929 if (adev->is_channel_status_set == false &&
5930 compare_device_type(&out->device_list,
5931 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005932 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305933 adev->is_channel_status_set = true;
5934 }
5935
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305936 if ((adev->use_old_pspd_mix_ctrl == true) &&
5937 (out->pspd_coeff_sent == false)) {
5938 /*
5939 * Need to resend pspd coefficients after stream started for
5940 * older kernel version as it does not save the coefficients
5941 * and also stream has to be started for coeff to apply.
5942 */
5943 usecase = get_usecase_from_list(adev, out->usecase);
5944 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305945 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305946 out->pspd_coeff_sent = true;
5947 }
5948 }
5949
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005950 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005951 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005952 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005953 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005954 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5955 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305956 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5957 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005958 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305959 out->send_next_track_params = false;
5960 out->is_compr_metadata_avail = false;
5961 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005962 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305963 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305964 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005965
Ashish Jain83a6cc22016-06-28 14:34:17 +05305966 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305967 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305968 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305969 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005970 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305971 return -EINVAL;
5972 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305973 audio_format_t dst_format = out->hal_op_format;
5974 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305975
Dieter Luecking5d57def2018-09-07 14:23:37 +02005976 /* prevent division-by-zero */
5977 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5978 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5979 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5980 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305981 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005982 ATRACE_END();
5983 return -EINVAL;
5984 }
5985
Ashish Jainf1eaa582016-05-23 20:54:24 +05305986 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5987 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5988
Ashish Jain83a6cc22016-06-28 14:34:17 +05305989 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305990 dst_format,
5991 buffer,
5992 src_format,
5993 frames);
5994
Ashish Jain83a6cc22016-06-28 14:34:17 +05305995 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305996 bytes_to_write);
5997
5998 /*Convert written bytes in audio flinger format*/
5999 if (ret > 0)
6000 ret = ((ret * format_to_bitwidth_table[out->format]) /
6001 format_to_bitwidth_table[dst_format]);
6002 }
6003 } else
6004 ret = compress_write(out->compr, buffer, bytes);
6005
Zhou Songc9672822017-08-16 16:01:39 +08006006 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6007 update_frames_written(out, bytes);
6008
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306009 if (ret < 0)
6010 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006011 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306012 /*msg to cb thread only if non blocking write is enabled*/
6013 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306014 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306016 } else if (-ENETRESET == ret) {
6017 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306018 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306019 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306020 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006021 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306022 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006023 }
Ashish Jain5106d362016-05-11 19:23:33 +05306024
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306025 /* Call compr start only when non-zero bytes of data is there to be rendered */
6026 if (!out->playback_started && ret > 0) {
6027 int status = compress_start(out->compr);
6028 if (status < 0) {
6029 ret = status;
6030 ALOGE("%s: compr start failed with err %d", __func__, errno);
6031 goto exit;
6032 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006033 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006034 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006035 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006036 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006037 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006038
6039 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6040 popcount(out->channel_mask),
6041 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 }
6043 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006044 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006045 return ret;
6046 } else {
6047 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006048 size_t bytes_to_write = bytes;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006049 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006050 if (out->muted)
6051 memset((void *)buffer, 0, bytes);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006052 pthread_mutex_unlock(&out->latch_lock);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006053 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6054 __func__, frames, frame_size, bytes_to_write);
6055
Aalique Grahame22e49102018-12-18 14:23:57 -08006056 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006057 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6058 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6059 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006060 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6061 int16_t *src = (int16_t *)buffer;
6062 int16_t *dst = (int16_t *)buffer;
6063
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006064 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006065 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006066 "out_write called for %s use case with wrong properties",
6067 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006068
6069 /*
6070 * FIXME: this can be removed once audio flinger mixer supports
6071 * mono output
6072 */
6073
6074 /*
6075 * Code below goes over each frame in the buffer and adds both
6076 * L and R samples and then divides by 2 to convert to mono
6077 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006078 if (channel_count == 2) {
6079 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6080 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6081 }
6082 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006083 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006084 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006085
6086 // Note: since out_get_presentation_position() is called alternating with out_write()
6087 // by AudioFlinger, we can check underruns using the prior timestamp read.
6088 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6089 if (out->last_fifo_valid) {
6090 // compute drain to see if there is an underrun.
6091 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306092 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6093 int64_t frames_by_time =
6094 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6095 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006096 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6097
6098 if (underrun > 0) {
6099 simple_stats_log(&out->fifo_underruns, underrun);
6100
6101 ALOGW("%s: underrun(%lld) "
6102 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6103 __func__,
6104 (long long)out->fifo_underruns.n,
6105 (long long)frames_by_time,
6106 (long long)out->last_fifo_frames_remaining);
6107 }
6108 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6109 }
6110
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306111 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006112
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006113 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006114
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006115 if (out->config.rate)
6116 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6117 out->config.rate;
6118
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006119 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006120 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6121
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006122 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006123 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006124 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306125 out->convert_buffer != NULL) {
6126
6127 memcpy_by_audio_format(out->convert_buffer,
6128 out->hal_op_format,
6129 buffer,
6130 out->hal_ip_format,
6131 out->config.period_size * out->config.channels);
6132
6133 ret = pcm_write(out->pcm, out->convert_buffer,
6134 (out->config.period_size *
6135 out->config.channels *
6136 format_to_bitwidth_table[out->hal_op_format]));
6137 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306138 /*
6139 * To avoid underrun in DSP when the application is not pumping
6140 * data at required rate, check for the no. of bytes and ignore
6141 * pcm_write if it is less than actual buffer size.
6142 * It is a work around to a change in compress VOIP driver.
6143 */
6144 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6145 bytes < (out->config.period_size * out->config.channels *
6146 audio_bytes_per_sample(out->format))) {
6147 size_t voip_buf_size =
6148 out->config.period_size * out->config.channels *
6149 audio_bytes_per_sample(out->format);
6150 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6151 __func__, bytes, voip_buf_size);
6152 usleep(((uint64_t)voip_buf_size - bytes) *
6153 1000000 / audio_stream_out_frame_size(stream) /
6154 out_get_sample_rate(&out->stream.common));
6155 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006156 } else {
6157 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6158 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6159 else
6160 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6161 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306162 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006163
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006164 release_out_focus(out);
6165
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306166 if (ret < 0)
6167 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006168 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306169 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006170 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006171 }
6172
6173exit:
Zhou Songc9672822017-08-16 16:01:39 +08006174 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306175 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306176 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 pthread_mutex_unlock(&out->lock);
6179
6180 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006181 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006182 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306183 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306184 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306185 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306186 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306187 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306188 out->standby = true;
6189 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306190 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006191 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6192 /* prevent division-by-zero */
6193 uint32_t stream_size = audio_stream_out_frame_size(stream);
6194 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006195
Dieter Luecking5d57def2018-09-07 14:23:37 +02006196 if ((stream_size == 0) || (srate == 0)) {
6197 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6198 ATRACE_END();
6199 return -EINVAL;
6200 }
6201 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6202 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006203 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306204 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006205 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006206 return ret;
6207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006208 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006209 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210 return bytes;
6211}
6212
6213static int out_get_render_position(const struct audio_stream_out *stream,
6214 uint32_t *dsp_frames)
6215{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006216 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006217
6218 if (dsp_frames == NULL)
6219 return -EINVAL;
6220
6221 *dsp_frames = 0;
6222 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006223 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306224
6225 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6226 * this operation and adev_close_output_stream(where out gets reset).
6227 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306228 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006229 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306230 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006231 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306232 return 0;
6233 }
6234
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006235 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306236 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306237 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006238 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306239 if (ret < 0)
6240 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006241 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306242 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006243 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306244 if (-ENETRESET == ret) {
6245 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306246 out->card_status = CARD_STATUS_OFFLINE;
6247 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306248 } else if(ret < 0) {
6249 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306250 ret = -EINVAL;
6251 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306252 /*
6253 * Handle corner case where compress session is closed during SSR
6254 * and timestamp is queried
6255 */
6256 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306257 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306258 } else if (out->prev_card_status_offline) {
6259 ALOGE("ERROR: previously sound card was offline,return error");
6260 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306261 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306262 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006263 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306264 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306265 pthread_mutex_unlock(&out->lock);
6266 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006267 } else if (audio_is_linear_pcm(out->format)) {
6268 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006269 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006270 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006271 } else
6272 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273}
6274
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006275static int out_add_audio_effect(const struct audio_stream *stream __unused,
6276 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006277{
6278 return 0;
6279}
6280
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006281static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6282 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006283{
6284 return 0;
6285}
6286
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006287static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6288 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006289{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306290 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006291}
6292
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006293static int out_get_presentation_position(const struct audio_stream_out *stream,
6294 uint64_t *frames, struct timespec *timestamp)
6295{
6296 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306297 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006298 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006299
Ashish Jain5106d362016-05-11 19:23:33 +05306300 /* below piece of code is not guarded against any lock because audioFliner serializes
6301 * this operation and adev_close_output_stream( where out gets reset).
6302 */
6303 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306304 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006305 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306306 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6307 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6308 return 0;
6309 }
6310
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006311 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006312
Ashish Jain5106d362016-05-11 19:23:33 +05306313 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6314 ret = compress_get_tstamp(out->compr, &dsp_frames,
6315 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006316 // Adjustment accounts for A2dp encoder latency with offload usecases
6317 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006318 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006319 unsigned long offset =
6320 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6321 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6322 }
Ashish Jain5106d362016-05-11 19:23:33 +05306323 ALOGVV("%s rendered frames %ld sample_rate %d",
6324 __func__, dsp_frames, out->sample_rate);
6325 *frames = dsp_frames;
6326 if (ret < 0)
6327 ret = -errno;
6328 if (-ENETRESET == ret) {
6329 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306330 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306331 ret = -EINVAL;
6332 } else
6333 ret = 0;
6334 /* this is the best we can do */
6335 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006336 } else {
6337 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006338 unsigned int avail;
6339 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006340 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006341 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006342
Andy Hunga1f48fa2019-07-01 18:14:53 -07006343 if (out->kernel_buffer_size > avail) {
6344 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6345 } else {
6346 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6347 __func__, avail, out->kernel_buffer_size);
6348 avail = out->kernel_buffer_size;
6349 frames_temp = out->last_fifo_frames_remaining = 0;
6350 }
6351 out->last_fifo_valid = true;
6352 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6353
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006354 if (out->written >= frames_temp)
6355 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006356
Andy Hunga1f48fa2019-07-01 18:14:53 -07006357 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6358 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6359
Weiyin Jiangd4633762018-03-16 12:05:03 +08006360 // This adjustment accounts for buffering after app processor.
6361 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006362 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006363 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006364 if (signed_frames >= frames_temp)
6365 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006366
Weiyin Jiangd4633762018-03-16 12:05:03 +08006367 // Adjustment accounts for A2dp encoder latency with non offload usecases
6368 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006369 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006370 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6371 if (signed_frames >= frames_temp)
6372 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006373 }
6374
6375 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006376 *frames = signed_frames;
6377 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006378 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006379 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6380 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006381 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306382 *frames = out->written;
6383 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306384 if (is_offload_usecase(out->usecase))
6385 ret = -EINVAL;
6386 else
6387 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006388 }
6389 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006390 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006391 return ret;
6392}
6393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006394static int out_set_callback(struct audio_stream_out *stream,
6395 stream_callback_t callback, void *cookie)
6396{
6397 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006398 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006399
6400 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006401 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006402 out->client_callback = callback;
6403 out->client_cookie = cookie;
6404 if (out->adsp_hdlr_stream_handle) {
6405 ret = audio_extn_adsp_hdlr_stream_set_callback(
6406 out->adsp_hdlr_stream_handle,
6407 callback,
6408 cookie);
6409 if (ret)
6410 ALOGW("%s:adsp hdlr callback registration failed %d",
6411 __func__, ret);
6412 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006413 pthread_mutex_unlock(&out->lock);
6414 return 0;
6415}
6416
6417static int out_pause(struct audio_stream_out* stream)
6418{
6419 struct stream_out *out = (struct stream_out *)stream;
6420 int status = -ENOSYS;
6421 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006422 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006423 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306424 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006425 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006426 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006427 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306428 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306429 status = compress_pause(out->compr);
6430
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006431 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006432
Mingming Yin21854652016-04-13 11:54:02 -07006433 if (audio_extn_passthru_is_active()) {
6434 ALOGV("offload use case, pause passthru");
6435 audio_extn_passthru_on_pause(out);
6436 }
6437
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306438 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006439 audio_extn_dts_notify_playback_state(out->usecase, 0,
6440 out->sample_rate, popcount(out->channel_mask),
6441 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006442 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006443 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006444 pthread_mutex_unlock(&out->lock);
6445 }
6446 return status;
6447}
6448
6449static int out_resume(struct audio_stream_out* stream)
6450{
6451 struct stream_out *out = (struct stream_out *)stream;
6452 int status = -ENOSYS;
6453 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006454 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006455 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306456 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006457 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006458 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006459 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306460 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306461 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006462 }
6463 if (!status) {
6464 out->offload_state = OFFLOAD_STATE_PLAYING;
6465 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306466 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006467 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6468 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006469 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006470 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006471 pthread_mutex_unlock(&out->lock);
6472 }
6473 return status;
6474}
6475
6476static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6477{
6478 struct stream_out *out = (struct stream_out *)stream;
6479 int status = -ENOSYS;
6480 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006481 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006483 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6484 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6485 else
6486 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6487 pthread_mutex_unlock(&out->lock);
6488 }
6489 return status;
6490}
6491
6492static int out_flush(struct audio_stream_out* stream)
6493{
6494 struct stream_out *out = (struct stream_out *)stream;
6495 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006496 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006497 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006498 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006499 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006500 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6501 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006502 } else {
6503 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6504 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006505 out->written = 0;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006506 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006507 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006508 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006509 return 0;
6510 }
6511 return -ENOSYS;
6512}
6513
Haynes Mathew George16081042017-05-31 17:16:49 -07006514static int out_stop(const struct audio_stream_out* stream)
6515{
6516 struct stream_out *out = (struct stream_out *)stream;
6517 struct audio_device *adev = out->dev;
6518 int ret = -ENOSYS;
6519
6520 ALOGV("%s", __func__);
6521 pthread_mutex_lock(&adev->lock);
6522 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6523 out->playback_started && out->pcm != NULL) {
6524 pcm_stop(out->pcm);
6525 ret = stop_output_stream(out);
6526 out->playback_started = false;
6527 }
6528 pthread_mutex_unlock(&adev->lock);
6529 return ret;
6530}
6531
6532static int out_start(const struct audio_stream_out* stream)
6533{
6534 struct stream_out *out = (struct stream_out *)stream;
6535 struct audio_device *adev = out->dev;
6536 int ret = -ENOSYS;
6537
6538 ALOGV("%s", __func__);
6539 pthread_mutex_lock(&adev->lock);
6540 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6541 !out->playback_started && out->pcm != NULL) {
6542 ret = start_output_stream(out);
6543 if (ret == 0) {
6544 out->playback_started = true;
6545 }
6546 }
6547 pthread_mutex_unlock(&adev->lock);
6548 return ret;
6549}
6550
6551/*
6552 * Modify config->period_count based on min_size_frames
6553 */
6554static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6555{
6556 int periodCountRequested = (min_size_frames + config->period_size - 1)
6557 / config->period_size;
6558 int periodCount = MMAP_PERIOD_COUNT_MIN;
6559
6560 ALOGV("%s original config.period_size = %d config.period_count = %d",
6561 __func__, config->period_size, config->period_count);
6562
6563 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6564 periodCount *= 2;
6565 }
6566 config->period_count = periodCount;
6567
6568 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6569}
6570
Phil Burkfe17efd2019-03-25 10:23:35 -07006571// Read offset for the positional timestamp from a persistent vendor property.
6572// This is to workaround apparent inaccuracies in the timing information that
6573// is used by the AAudio timing model. The inaccuracies can cause glitches.
6574static int64_t get_mmap_out_time_offset() {
6575 const int32_t kDefaultOffsetMicros = 0;
6576 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006577 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006578 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6579 return mmap_time_offset_micros * (int64_t)1000;
6580}
6581
Haynes Mathew George16081042017-05-31 17:16:49 -07006582static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6583 int32_t min_size_frames,
6584 struct audio_mmap_buffer_info *info)
6585{
6586 struct stream_out *out = (struct stream_out *)stream;
6587 struct audio_device *adev = out->dev;
6588 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006589 unsigned int offset1 = 0;
6590 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006591 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006592 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006593 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006594
Arun Mirpuri5d170872019-03-26 13:21:31 -07006595 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306596 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006597 pthread_mutex_lock(&adev->lock);
6598
Sharad Sanglec6f32552018-05-04 16:15:38 +05306599 if (CARD_STATUS_OFFLINE == out->card_status ||
6600 CARD_STATUS_OFFLINE == adev->card_status) {
6601 ALOGW("out->card_status or adev->card_status offline, try again");
6602 ret = -EIO;
6603 goto exit;
6604 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306605 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006606 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6607 ret = -EINVAL;
6608 goto exit;
6609 }
6610 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6611 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6612 ret = -ENOSYS;
6613 goto exit;
6614 }
6615 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6616 if (out->pcm_device_id < 0) {
6617 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6618 __func__, out->pcm_device_id, out->usecase);
6619 ret = -EINVAL;
6620 goto exit;
6621 }
6622
6623 adjust_mmap_period_count(&out->config, min_size_frames);
6624
Arun Mirpuri5d170872019-03-26 13:21:31 -07006625 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006626 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6627 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6628 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306629 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306630 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6631 out->card_status = CARD_STATUS_OFFLINE;
6632 adev->card_status = CARD_STATUS_OFFLINE;
6633 ret = -EIO;
6634 goto exit;
6635 }
6636
Haynes Mathew George16081042017-05-31 17:16:49 -07006637 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6638 step = "open";
6639 ret = -ENODEV;
6640 goto exit;
6641 }
6642 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6643 if (ret < 0) {
6644 step = "begin";
6645 goto exit;
6646 }
juyuchen626833d2019-06-04 16:48:02 +08006647
6648 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006649 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006650 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006651 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006652 ret = platform_get_mmap_data_fd(adev->platform,
6653 out->pcm_device_id, 0 /*playback*/,
6654 &info->shared_memory_fd,
6655 &mmap_size);
6656 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006657 // Fall back to non exclusive mode
6658 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6659 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006660 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6661 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6662
Arun Mirpuri5d170872019-03-26 13:21:31 -07006663 if (mmap_size < buffer_size) {
6664 step = "mmap";
6665 goto exit;
6666 }
juyuchen626833d2019-06-04 16:48:02 +08006667 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006668 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006669 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006670 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006671
6672 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6673 if (ret < 0) {
6674 step = "commit";
6675 goto exit;
6676 }
6677
Phil Burkfe17efd2019-03-25 10:23:35 -07006678 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6679
Haynes Mathew George16081042017-05-31 17:16:49 -07006680 out->standby = false;
6681 ret = 0;
6682
Arun Mirpuri5d170872019-03-26 13:21:31 -07006683 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006684 __func__, info->shared_memory_address, info->buffer_size_frames);
6685
6686exit:
6687 if (ret != 0) {
6688 if (out->pcm == NULL) {
6689 ALOGE("%s: %s - %d", __func__, step, ret);
6690 } else {
6691 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6692 pcm_close(out->pcm);
6693 out->pcm = NULL;
6694 }
6695 }
6696 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306697 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006698 return ret;
6699}
6700
6701static int out_get_mmap_position(const struct audio_stream_out *stream,
6702 struct audio_mmap_position *position)
6703{
6704 struct stream_out *out = (struct stream_out *)stream;
6705 ALOGVV("%s", __func__);
6706 if (position == NULL) {
6707 return -EINVAL;
6708 }
6709 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006710 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006711 return -ENOSYS;
6712 }
6713 if (out->pcm == NULL) {
6714 return -ENOSYS;
6715 }
6716
6717 struct timespec ts = { 0, 0 };
6718 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6719 if (ret < 0) {
6720 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6721 return ret;
6722 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006723 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6724 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006725 return 0;
6726}
6727
6728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006729/** audio_stream_in implementation **/
6730static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6731{
6732 struct stream_in *in = (struct stream_in *)stream;
6733
6734 return in->config.rate;
6735}
6736
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006737static int in_set_sample_rate(struct audio_stream *stream __unused,
6738 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006739{
6740 return -ENOSYS;
6741}
6742
6743static size_t in_get_buffer_size(const struct audio_stream *stream)
6744{
6745 struct stream_in *in = (struct stream_in *)stream;
6746
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006747 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6748 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006749 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6750 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306751 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306752 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006753
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006754 return in->config.period_size * in->af_period_multiplier *
6755 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006756}
6757
6758static uint32_t in_get_channels(const struct audio_stream *stream)
6759{
6760 struct stream_in *in = (struct stream_in *)stream;
6761
6762 return in->channel_mask;
6763}
6764
6765static audio_format_t in_get_format(const struct audio_stream *stream)
6766{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006767 struct stream_in *in = (struct stream_in *)stream;
6768
6769 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770}
6771
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006772static int in_set_format(struct audio_stream *stream __unused,
6773 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006774{
6775 return -ENOSYS;
6776}
6777
6778static int in_standby(struct audio_stream *stream)
6779{
6780 struct stream_in *in = (struct stream_in *)stream;
6781 struct audio_device *adev = in->dev;
6782 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306783 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6784 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006785 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306786
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006787 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006788 if (!in->standby && in->is_st_session) {
6789 ALOGD("%s: sound trigger pcm stop lab", __func__);
6790 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006791 if (adev->num_va_sessions > 0)
6792 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006793 in->standby = 1;
6794 }
6795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006797 if (adev->adm_deregister_stream)
6798 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6799
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006800 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006801 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006802 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006803 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006804 voice_extn_compress_voip_close_input_stream(stream);
6805 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006806 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6807 do_stop = in->capture_started;
6808 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006809 if (in->mmap_shared_memory_fd >= 0) {
6810 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6811 __func__, in->mmap_shared_memory_fd);
6812 close(in->mmap_shared_memory_fd);
6813 in->mmap_shared_memory_fd = -1;
6814 }
Zhou Songa8895042016-07-05 17:54:22 +08006815 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306816 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306817 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006818 }
6819
Arun Mirpuri5d170872019-03-26 13:21:31 -07006820 if (in->pcm) {
6821 ATRACE_BEGIN("pcm_in_close");
6822 pcm_close(in->pcm);
6823 ATRACE_END();
6824 in->pcm = NULL;
6825 }
6826
Carter Hsu2e429db2019-05-14 18:50:52 +08006827 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006828 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006829
George Gao3018ede2019-10-23 13:23:00 -07006830 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6831 if (adev->num_va_sessions > 0)
6832 adev->num_va_sessions--;
6833 }
Quinn Malef6050362019-01-30 15:55:40 -08006834
Eric Laurent150dbfe2013-02-27 14:31:02 -08006835 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 }
6837 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006838 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006839 return status;
6840}
6841
Aalique Grahame22e49102018-12-18 14:23:57 -08006842static int in_dump(const struct audio_stream *stream,
6843 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844{
Aalique Grahame22e49102018-12-18 14:23:57 -08006845 struct stream_in *in = (struct stream_in *)stream;
6846
6847 // We try to get the lock for consistency,
6848 // but it isn't necessary for these variables.
6849 // If we're not in standby, we may be blocked on a read.
6850 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6851 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6852 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6853 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6854
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006855 char buffer[256]; // for statistics formatting
6856 if (in->start_latency_ms.n > 0) {
6857 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6858 dprintf(fd, " Start latency ms: %s\n", buffer);
6859 }
6860
Aalique Grahame22e49102018-12-18 14:23:57 -08006861 if (locked) {
6862 pthread_mutex_unlock(&in->lock);
6863 }
6864
6865 // dump error info
6866 (void)error_log_dump(
6867 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869 return 0;
6870}
6871
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306872static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6873{
6874 if (!stream || !parms)
6875 return;
6876
6877 struct stream_in *in = (struct stream_in *)stream;
6878 struct audio_device *adev = in->dev;
6879
6880 card_status_t status;
6881 int card;
6882 if (parse_snd_card_status(parms, &card, &status) < 0)
6883 return;
6884
6885 pthread_mutex_lock(&adev->lock);
6886 bool valid_cb = (card == adev->snd_card);
6887 pthread_mutex_unlock(&adev->lock);
6888
6889 if (!valid_cb)
6890 return;
6891
6892 lock_input_stream(in);
6893 if (in->card_status != status)
6894 in->card_status = status;
6895 pthread_mutex_unlock(&in->lock);
6896
6897 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6898 use_case_table[in->usecase],
6899 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6900
6901 // a better solution would be to report error back to AF and let
6902 // it put the stream to standby
6903 if (status == CARD_STATUS_OFFLINE)
6904 in_standby(&in->stream.common);
6905
6906 return;
6907}
6908
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006909int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006910 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006911 audio_source_t source)
6912{
6913 struct audio_device *adev = in->dev;
6914 int ret = 0;
6915
6916 lock_input_stream(in);
6917 pthread_mutex_lock(&adev->lock);
6918
6919 /* no audio source uses val == 0 */
6920 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6921 in->source = source;
6922 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6923 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6924 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6925 (in->config.rate == 8000 || in->config.rate == 16000 ||
6926 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6927 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6928 ret = voice_extn_compress_voip_open_input_stream(in);
6929 if (ret != 0) {
6930 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6931 __func__, ret);
6932 }
6933 }
6934 }
6935
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006936 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6937 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006938 // Workaround: If routing to an non existing usb device, fail gracefully
6939 // The routing request will otherwise block during 10 second
6940 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006941 struct str_parms *usb_addr =
6942 str_parms_create_str(get_usb_device_address(devices));
6943 if (is_usb_in_device_type(devices) && usb_addr &&
6944 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006945 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6946 ret = -ENOSYS;
6947 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006948 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006949 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006950 if (!in->standby && !in->is_st_session) {
6951 ALOGV("update input routing change");
6952 // inform adm before actual routing to prevent glitches.
6953 if (adev->adm_on_routing_change) {
6954 adev->adm_on_routing_change(adev->adm_data,
6955 in->capture_handle);
6956 ret = select_devices(adev, in->usecase);
6957 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6958 adev->adm_routing_changed = true;
6959 }
6960 }
6961 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006962 if (usb_addr)
6963 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006964 }
6965 pthread_mutex_unlock(&adev->lock);
6966 pthread_mutex_unlock(&in->lock);
6967
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07006968 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006969 return ret;
6970}
6971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006972static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6973{
6974 struct stream_in *in = (struct stream_in *)stream;
6975 struct audio_device *adev = in->dev;
6976 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006977 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306978 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006979
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306980 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006981 parms = str_parms_create_str(kvpairs);
6982
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306983 if (!parms)
6984 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006985 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006986 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006987
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306988 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6989 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306990 strlcpy(in->profile, value, sizeof(in->profile));
6991 ALOGV("updating stream profile with value '%s'", in->profile);
6992 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6993 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006994 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306995 in->sample_rate, in->bit_width,
6996 in->profile, &in->app_type_cfg);
6997 }
6998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006999 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007000 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007001
7002 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307003error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307004 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007005}
7006
7007static char* in_get_parameters(const struct audio_stream *stream,
7008 const char *keys)
7009{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007010 struct stream_in *in = (struct stream_in *)stream;
7011 struct str_parms *query = str_parms_create_str(keys);
7012 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007013 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007014
7015 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007016 if (reply) {
7017 str_parms_destroy(reply);
7018 }
7019 if (query) {
7020 str_parms_destroy(query);
7021 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007022 ALOGE("in_get_parameters: failed to create query or reply");
7023 return NULL;
7024 }
7025
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007026 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007027
7028 voice_extn_in_get_parameters(in, query, reply);
7029
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007030 stream_get_parameter_channels(query, reply,
7031 &in->supported_channel_masks[0]);
7032 stream_get_parameter_formats(query, reply,
7033 &in->supported_formats[0]);
7034 stream_get_parameter_rates(query, reply,
7035 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007036 str = str_parms_to_str(reply);
7037 str_parms_destroy(query);
7038 str_parms_destroy(reply);
7039
7040 ALOGV("%s: exit: returns - %s", __func__, str);
7041 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007042}
7043
Aalique Grahame22e49102018-12-18 14:23:57 -08007044static int in_set_gain(struct audio_stream_in *stream,
7045 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007046{
Aalique Grahame22e49102018-12-18 14:23:57 -08007047 struct stream_in *in = (struct stream_in *)stream;
7048 char mixer_ctl_name[128];
7049 struct mixer_ctl *ctl;
7050 int ctl_value;
7051
7052 ALOGV("%s: gain %f", __func__, gain);
7053
7054 if (stream == NULL)
7055 return -EINVAL;
7056
7057 /* in_set_gain() only used to silence MMAP capture for now */
7058 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7059 return -ENOSYS;
7060
7061 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7062
7063 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7064 if (!ctl) {
7065 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7066 __func__, mixer_ctl_name);
7067 return -ENOSYS;
7068 }
7069
7070 if (gain < RECORD_GAIN_MIN)
7071 gain = RECORD_GAIN_MIN;
7072 else if (gain > RECORD_GAIN_MAX)
7073 gain = RECORD_GAIN_MAX;
7074 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7075
7076 mixer_ctl_set_value(ctl, 0, ctl_value);
7077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007078 return 0;
7079}
7080
7081static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7082 size_t bytes)
7083{
7084 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307085
7086 if (in == NULL) {
7087 ALOGE("%s: stream_in ptr is NULL", __func__);
7088 return -EINVAL;
7089 }
7090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007091 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307092 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307093 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007094
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007095 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307096
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007097 if (in->is_st_session) {
7098 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7099 /* Read from sound trigger HAL */
7100 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007101 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007102 if (adev->num_va_sessions < UINT_MAX)
7103 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007104 in->standby = 0;
7105 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007106 pthread_mutex_unlock(&in->lock);
7107 return bytes;
7108 }
7109
Haynes Mathew George16081042017-05-31 17:16:49 -07007110 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7111 ret = -ENOSYS;
7112 goto exit;
7113 }
7114
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007115 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7116 !in->standby && adev->adm_routing_changed) {
7117 ret = -ENOSYS;
7118 goto exit;
7119 }
7120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007121 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007122 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7123
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007124 pthread_mutex_lock(&adev->lock);
7125 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7126 ret = voice_extn_compress_voip_start_input_stream(in);
7127 else
7128 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007129 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7130 if (adev->num_va_sessions < UINT_MAX)
7131 adev->num_va_sessions++;
7132 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007133 pthread_mutex_unlock(&adev->lock);
7134 if (ret != 0) {
7135 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007136 }
7137 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007138
7139 // log startup time in ms.
7140 simple_stats_log(
7141 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007143
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307144 /* Avoid read if capture_stopped is set */
7145 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7146 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7147 ret = -EINVAL;
7148 goto exit;
7149 }
7150
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007151 // what's the duration requested by the client?
7152 long ns = 0;
7153
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307154 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007155 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7156 in->config.rate;
7157
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007158 ret = request_in_focus(in, ns);
7159 if (ret != 0)
7160 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007161 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007162
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307163 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307164 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7165 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307166 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007167 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307168 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007169 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007170 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007171 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007172 } else if (audio_extn_ffv_get_stream() == in) {
7173 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307174 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007175 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307176 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7177 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7178 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7179 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307180 ret = -EINVAL;
7181 goto exit;
7182 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307183 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307184 ret = -errno;
7185 }
7186 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307187 /* bytes read is always set to bytes for non compress usecases */
7188 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007189 }
7190
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007191 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007193 /*
Quinn Malef6050362019-01-30 15:55:40 -08007194 * Instead of writing zeroes here, we could trust the hardware to always
7195 * provide zeroes when muted. This is also muted with voice recognition
7196 * usecases so that other clients do not have access to voice recognition
7197 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007198 */
Quinn Malef6050362019-01-30 15:55:40 -08007199 if ((ret == 0 && voice_get_mic_mute(adev) &&
7200 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007201 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7202 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007203 (adev->num_va_sessions &&
7204 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7205 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7206 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207 memset(buffer, 0, bytes);
7208
7209exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307210 frame_size = audio_stream_in_frame_size(stream);
7211 if (frame_size > 0)
7212 in->frames_read += bytes_read/frame_size;
7213
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007214 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307215 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007216 pthread_mutex_unlock(&in->lock);
7217
7218 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307219 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307220 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307221 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307222 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307223 in->standby = true;
7224 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307225 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307226 bytes_read = bytes;
7227 memset(buffer, 0, bytes);
7228 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007229 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007230 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7231 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007232 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307233 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307234 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007235 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307236 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237}
7238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007239static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007240{
7241 return 0;
7242}
7243
Aalique Grahame22e49102018-12-18 14:23:57 -08007244static int in_get_capture_position(const struct audio_stream_in *stream,
7245 int64_t *frames, int64_t *time)
7246{
7247 if (stream == NULL || frames == NULL || time == NULL) {
7248 return -EINVAL;
7249 }
7250 struct stream_in *in = (struct stream_in *)stream;
7251 int ret = -ENOSYS;
7252
7253 lock_input_stream(in);
7254 // note: ST sessions do not close the alsa pcm driver synchronously
7255 // on standby. Therefore, we may return an error even though the
7256 // pcm stream is still opened.
7257 if (in->standby) {
7258 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7259 "%s stream in standby but pcm not NULL for non ST session", __func__);
7260 goto exit;
7261 }
7262 if (in->pcm) {
7263 struct timespec timestamp;
7264 unsigned int avail;
7265 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7266 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007267 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007268 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007269 ret = 0;
7270 }
7271 }
7272exit:
7273 pthread_mutex_unlock(&in->lock);
7274 return ret;
7275}
7276
Carter Hsu2e429db2019-05-14 18:50:52 +08007277static int in_update_effect_list(bool add, effect_handle_t effect,
7278 struct listnode *head)
7279{
7280 struct listnode *node;
7281 struct in_effect_list *elist = NULL;
7282 struct in_effect_list *target = NULL;
7283 int ret = 0;
7284
7285 if (!head)
7286 return ret;
7287
7288 list_for_each(node, head) {
7289 elist = node_to_item(node, struct in_effect_list, list);
7290 if (elist->handle == effect) {
7291 target = elist;
7292 break;
7293 }
7294 }
7295
7296 if (add) {
7297 if (target) {
7298 ALOGD("effect %p already exist", effect);
7299 return ret;
7300 }
7301
7302 target = (struct in_effect_list *)
7303 calloc(1, sizeof(struct in_effect_list));
7304
7305 if (!target) {
7306 ALOGE("%s:fail to allocate memory", __func__);
7307 return -ENOMEM;
7308 }
7309
7310 target->handle = effect;
7311 list_add_tail(head, &target->list);
7312 } else {
7313 if (target) {
7314 list_remove(&target->list);
7315 free(target);
7316 }
7317 }
7318
7319 return ret;
7320}
7321
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007322static int add_remove_audio_effect(const struct audio_stream *stream,
7323 effect_handle_t effect,
7324 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007326 struct stream_in *in = (struct stream_in *)stream;
7327 int status = 0;
7328 effect_descriptor_t desc;
7329
7330 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007331 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7332
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007333 if (status != 0)
7334 return status;
7335
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007336 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007337 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007338 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007339 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7340 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007341 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007342
7343 in_update_effect_list(enable, effect, &in->aec_list);
7344 enable = !list_empty(&in->aec_list);
7345 if (enable == in->enable_aec)
7346 goto exit;
7347
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007348 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007349 ALOGD("AEC enable %d", enable);
7350
Aalique Grahame22e49102018-12-18 14:23:57 -08007351 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7352 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7353 in->dev->enable_voicerx = enable;
7354 struct audio_usecase *usecase;
7355 struct listnode *node;
7356 list_for_each(node, &in->dev->usecase_list) {
7357 usecase = node_to_item(node, struct audio_usecase, list);
7358 if (usecase->type == PCM_PLAYBACK)
7359 select_devices(in->dev, usecase->id);
7360 }
7361 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007362 if (!in->standby) {
7363 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7364 select_devices(in->dev, in->usecase);
7365 }
7366
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007367 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007368 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7369
7370 in_update_effect_list(enable, effect, &in->ns_list);
7371 enable = !list_empty(&in->ns_list);
7372 if (enable == in->enable_ns)
7373 goto exit;
7374
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007375 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007376 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007377 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007378 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7379 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007380 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7381 select_devices(in->dev, in->usecase);
7382 } else
7383 select_devices(in->dev, in->usecase);
7384 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007385 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007386exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007387 pthread_mutex_unlock(&in->dev->lock);
7388 pthread_mutex_unlock(&in->lock);
7389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007390 return 0;
7391}
7392
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007393static int in_add_audio_effect(const struct audio_stream *stream,
7394 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007395{
Eric Laurent994a6932013-07-17 11:51:42 -07007396 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007397 return add_remove_audio_effect(stream, effect, true);
7398}
7399
7400static int in_remove_audio_effect(const struct audio_stream *stream,
7401 effect_handle_t effect)
7402{
Eric Laurent994a6932013-07-17 11:51:42 -07007403 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007404 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007405}
7406
Derek Chenf939fb72018-11-13 13:34:41 -08007407streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7408 audio_io_handle_t input)
7409{
7410 struct listnode *node;
7411
7412 list_for_each(node, &dev->active_inputs_list) {
7413 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7414 streams_input_ctxt_t,
7415 list);
7416 if (in_ctxt->input->capture_handle == input) {
7417 return in_ctxt;
7418 }
7419 }
7420 return NULL;
7421}
7422
7423streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7424 audio_io_handle_t output)
7425{
7426 struct listnode *node;
7427
7428 list_for_each(node, &dev->active_outputs_list) {
7429 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7430 streams_output_ctxt_t,
7431 list);
7432 if (out_ctxt->output->handle == output) {
7433 return out_ctxt;
7434 }
7435 }
7436 return NULL;
7437}
7438
Haynes Mathew George16081042017-05-31 17:16:49 -07007439static int in_stop(const struct audio_stream_in* stream)
7440{
7441 struct stream_in *in = (struct stream_in *)stream;
7442 struct audio_device *adev = in->dev;
7443
7444 int ret = -ENOSYS;
7445 ALOGV("%s", __func__);
7446 pthread_mutex_lock(&adev->lock);
7447 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7448 in->capture_started && in->pcm != NULL) {
7449 pcm_stop(in->pcm);
7450 ret = stop_input_stream(in);
7451 in->capture_started = false;
7452 }
7453 pthread_mutex_unlock(&adev->lock);
7454 return ret;
7455}
7456
7457static int in_start(const struct audio_stream_in* stream)
7458{
7459 struct stream_in *in = (struct stream_in *)stream;
7460 struct audio_device *adev = in->dev;
7461 int ret = -ENOSYS;
7462
7463 ALOGV("%s in %p", __func__, in);
7464 pthread_mutex_lock(&adev->lock);
7465 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7466 !in->capture_started && in->pcm != NULL) {
7467 if (!in->capture_started) {
7468 ret = start_input_stream(in);
7469 if (ret == 0) {
7470 in->capture_started = true;
7471 }
7472 }
7473 }
7474 pthread_mutex_unlock(&adev->lock);
7475 return ret;
7476}
7477
Phil Burke0a86d12019-02-16 22:28:11 -08007478// Read offset for the positional timestamp from a persistent vendor property.
7479// This is to workaround apparent inaccuracies in the timing information that
7480// is used by the AAudio timing model. The inaccuracies can cause glitches.
7481static int64_t in_get_mmap_time_offset() {
7482 const int32_t kDefaultOffsetMicros = 0;
7483 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007484 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007485 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7486 return mmap_time_offset_micros * (int64_t)1000;
7487}
7488
Haynes Mathew George16081042017-05-31 17:16:49 -07007489static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7490 int32_t min_size_frames,
7491 struct audio_mmap_buffer_info *info)
7492{
7493 struct stream_in *in = (struct stream_in *)stream;
7494 struct audio_device *adev = in->dev;
7495 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007496 unsigned int offset1 = 0;
7497 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007498 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007499 uint32_t mmap_size = 0;
7500 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007501
7502 pthread_mutex_lock(&adev->lock);
7503 ALOGV("%s in %p", __func__, in);
7504
Sharad Sanglec6f32552018-05-04 16:15:38 +05307505 if (CARD_STATUS_OFFLINE == in->card_status||
7506 CARD_STATUS_OFFLINE == adev->card_status) {
7507 ALOGW("in->card_status or adev->card_status offline, try again");
7508 ret = -EIO;
7509 goto exit;
7510 }
7511
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307512 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007513 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7514 ret = -EINVAL;
7515 goto exit;
7516 }
7517 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7518 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7519 ALOGV("%s in %p", __func__, in);
7520 ret = -ENOSYS;
7521 goto exit;
7522 }
7523 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7524 if (in->pcm_device_id < 0) {
7525 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7526 __func__, in->pcm_device_id, in->usecase);
7527 ret = -EINVAL;
7528 goto exit;
7529 }
7530
7531 adjust_mmap_period_count(&in->config, min_size_frames);
7532
7533 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7534 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7535 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7536 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307537 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307538 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7539 in->card_status = CARD_STATUS_OFFLINE;
7540 adev->card_status = CARD_STATUS_OFFLINE;
7541 ret = -EIO;
7542 goto exit;
7543 }
7544
Haynes Mathew George16081042017-05-31 17:16:49 -07007545 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7546 step = "open";
7547 ret = -ENODEV;
7548 goto exit;
7549 }
7550
7551 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7552 if (ret < 0) {
7553 step = "begin";
7554 goto exit;
7555 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007556
juyuchen626833d2019-06-04 16:48:02 +08007557 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007558 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7559 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7560 info->burst_size_frames = in->config.period_size;
7561 ret = platform_get_mmap_data_fd(adev->platform,
7562 in->pcm_device_id, 1 /*capture*/,
7563 &info->shared_memory_fd,
7564 &mmap_size);
7565 if (ret < 0) {
7566 // Fall back to non exclusive mode
7567 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7568 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007569 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7570 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7571
Arun Mirpuri5d170872019-03-26 13:21:31 -07007572 if (mmap_size < buffer_size) {
7573 step = "mmap";
7574 goto exit;
7575 }
juyuchen626833d2019-06-04 16:48:02 +08007576 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007577 }
7578
7579 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007580
7581 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7582 if (ret < 0) {
7583 step = "commit";
7584 goto exit;
7585 }
7586
Phil Burke0a86d12019-02-16 22:28:11 -08007587 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7588
Haynes Mathew George16081042017-05-31 17:16:49 -07007589 in->standby = false;
7590 ret = 0;
7591
7592 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7593 __func__, info->shared_memory_address, info->buffer_size_frames);
7594
7595exit:
7596 if (ret != 0) {
7597 if (in->pcm == NULL) {
7598 ALOGE("%s: %s - %d", __func__, step, ret);
7599 } else {
7600 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7601 pcm_close(in->pcm);
7602 in->pcm = NULL;
7603 }
7604 }
7605 pthread_mutex_unlock(&adev->lock);
7606 return ret;
7607}
7608
7609static int in_get_mmap_position(const struct audio_stream_in *stream,
7610 struct audio_mmap_position *position)
7611{
7612 struct stream_in *in = (struct stream_in *)stream;
7613 ALOGVV("%s", __func__);
7614 if (position == NULL) {
7615 return -EINVAL;
7616 }
7617 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7618 return -ENOSYS;
7619 }
7620 if (in->pcm == NULL) {
7621 return -ENOSYS;
7622 }
7623 struct timespec ts = { 0, 0 };
7624 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7625 if (ret < 0) {
7626 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7627 return ret;
7628 }
Phil Burke0a86d12019-02-16 22:28:11 -08007629 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7630 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007631 return 0;
7632}
7633
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307634static int in_get_active_microphones(const struct audio_stream_in *stream,
7635 struct audio_microphone_characteristic_t *mic_array,
7636 size_t *mic_count) {
7637 struct stream_in *in = (struct stream_in *)stream;
7638 struct audio_device *adev = in->dev;
7639 ALOGVV("%s", __func__);
7640
7641 lock_input_stream(in);
7642 pthread_mutex_lock(&adev->lock);
7643 int ret = platform_get_active_microphones(adev->platform,
7644 audio_channel_count_from_in_mask(in->channel_mask),
7645 in->usecase, mic_array, mic_count);
7646 pthread_mutex_unlock(&adev->lock);
7647 pthread_mutex_unlock(&in->lock);
7648
7649 return ret;
7650}
7651
7652static int adev_get_microphones(const struct audio_hw_device *dev,
7653 struct audio_microphone_characteristic_t *mic_array,
7654 size_t *mic_count) {
7655 struct audio_device *adev = (struct audio_device *)dev;
7656 ALOGVV("%s", __func__);
7657
7658 pthread_mutex_lock(&adev->lock);
7659 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7660 pthread_mutex_unlock(&adev->lock);
7661
7662 return ret;
7663}
juyuchendb308c22019-01-21 11:57:17 -07007664
7665static void in_update_sink_metadata(struct audio_stream_in *stream,
7666 const struct sink_metadata *sink_metadata) {
7667
7668 if (stream == NULL
7669 || sink_metadata == NULL
7670 || sink_metadata->tracks == NULL) {
7671 return;
7672 }
7673
7674 int error = 0;
7675 struct stream_in *in = (struct stream_in *)stream;
7676 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007677 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007678 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007679
7680 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007681
7682 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007683 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007684
7685 lock_input_stream(in);
7686 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007687 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007688
Zhou Song62ea0282020-03-22 19:53:01 +08007689 is_ha_usecase = adev->ha_proxy_enable ?
7690 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7691 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7692 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007693 && adev->voice_tx_output != NULL) {
7694 /* Use the rx device from afe-proxy record to route voice call because
7695 there is no routing if tx device is on primary hal and rx device
7696 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007697 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007698
7699 if (!voice_is_call_state_active(adev)) {
7700 if (adev->mode == AUDIO_MODE_IN_CALL) {
7701 adev->current_call_output = adev->voice_tx_output;
7702 error = voice_start_call(adev);
7703 if (error != 0)
7704 ALOGE("%s: start voice call failed %d", __func__, error);
7705 }
7706 } else {
7707 adev->current_call_output = adev->voice_tx_output;
7708 voice_update_devices_for_all_voice_usecases(adev);
7709 }
7710 }
7711
7712 pthread_mutex_unlock(&adev->lock);
7713 pthread_mutex_unlock(&in->lock);
7714}
7715
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307716int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007717 audio_io_handle_t handle,
7718 audio_devices_t devices,
7719 audio_output_flags_t flags,
7720 struct audio_config *config,
7721 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007722 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007723{
7724 struct audio_device *adev = (struct audio_device *)dev;
7725 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307726 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007727 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007728 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307729 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007730 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7731 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7732 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7733 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007734 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007735 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7736 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007737 bool force_haptic_path =
7738 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007739 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007740#ifdef AUDIO_GKI_ENABLED
7741 __s32 *generic_dec;
7742#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007743
kunleizdff872d2018-08-20 14:40:33 +08007744 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007745 is_usb_dev = false;
7746 devices = AUDIO_DEVICE_OUT_SPEAKER;
7747 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7748 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007749 if (config->format == AUDIO_FORMAT_DEFAULT)
7750 config->format = AUDIO_FORMAT_PCM_16_BIT;
7751 if (config->sample_rate == 0)
7752 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7753 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7754 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007755 }
7756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007757 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307758
Rahul Sharma99770982019-03-06 17:05:26 +05307759 pthread_mutex_lock(&adev->lock);
7760 if (out_get_stream(adev, handle) != NULL) {
7761 ALOGW("%s, output stream already opened", __func__);
7762 ret = -EEXIST;
7763 }
7764 pthread_mutex_unlock(&adev->lock);
7765 if (ret)
7766 return ret;
7767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007768 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7769
Mingming Yin3a941d42016-02-17 18:08:05 -08007770 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007771 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7772 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307773
7774
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007775 if (!out) {
7776 return -ENOMEM;
7777 }
7778
Haynes Mathew George204045b2015-02-25 20:32:03 -08007779 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007780 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007781 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007782 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007783 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007785 if (devices == AUDIO_DEVICE_NONE)
7786 devices = AUDIO_DEVICE_OUT_SPEAKER;
7787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007788 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007789 list_init(&out->device_list);
7790 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007791 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007792 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007793 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307794 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307795 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7796 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7797 else
7798 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007799 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007800 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007801 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307802 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307803 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307804 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007805 out->hal_output_suspend_supported = 0;
7806 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307807 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307808 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307809 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007810 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007811
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307812 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307813 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007814 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7815
Aalique Grahame22e49102018-12-18 14:23:57 -08007816 if (direct_dev &&
7817 (audio_is_linear_pcm(out->format) ||
7818 config->format == AUDIO_FORMAT_DEFAULT) &&
7819 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7820 audio_format_t req_format = config->format;
7821 audio_channel_mask_t req_channel_mask = config->channel_mask;
7822 uint32_t req_sample_rate = config->sample_rate;
7823
7824 pthread_mutex_lock(&adev->lock);
7825 if (is_hdmi) {
7826 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7827 ret = read_hdmi_sink_caps(out);
7828 if (config->sample_rate == 0)
7829 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7830 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7831 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7832 if (config->format == AUDIO_FORMAT_DEFAULT)
7833 config->format = AUDIO_FORMAT_PCM_16_BIT;
7834 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007835 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7836 &config->format,
7837 &out->supported_formats[0],
7838 MAX_SUPPORTED_FORMATS,
7839 &config->channel_mask,
7840 &out->supported_channel_masks[0],
7841 MAX_SUPPORTED_CHANNEL_MASKS,
7842 &config->sample_rate,
7843 &out->supported_sample_rates[0],
7844 MAX_SUPPORTED_SAMPLE_RATES);
7845 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007846 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007847
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007848 pthread_mutex_unlock(&adev->lock);
7849 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007850 if (ret == -ENOSYS) {
7851 /* ignore and go with default */
7852 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007853 }
7854 // For MMAP NO IRQ, allow conversions in ADSP
7855 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7856 goto error_open;
7857 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007858 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007859 goto error_open;
7860 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007861
7862 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7863 config->sample_rate = req_sample_rate;
7864 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7865 config->channel_mask = req_channel_mask;
7866 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7867 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007868 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007869
7870 out->sample_rate = config->sample_rate;
7871 out->channel_mask = config->channel_mask;
7872 out->format = config->format;
7873 if (is_hdmi) {
7874 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7875 out->config = pcm_config_hdmi_multi;
7876 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7877 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7878 out->config = pcm_config_mmap_playback;
7879 out->stream.start = out_start;
7880 out->stream.stop = out_stop;
7881 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7882 out->stream.get_mmap_position = out_get_mmap_position;
7883 } else {
7884 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7885 out->config = pcm_config_hifi;
7886 }
7887
7888 out->config.rate = out->sample_rate;
7889 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7890 if (is_hdmi) {
7891 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7892 audio_bytes_per_sample(out->format));
7893 }
7894 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007895 }
7896
Derek Chenf6318be2017-06-12 17:16:24 -04007897 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007898 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007899 /* extract car audio stream index */
7900 out->car_audio_stream =
7901 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7902 if (out->car_audio_stream < 0) {
7903 ALOGE("%s: invalid car audio stream %x",
7904 __func__, out->car_audio_stream);
7905 ret = -EINVAL;
7906 goto error_open;
7907 }
Derek Chen5f67a942020-02-24 23:08:13 -08007908 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007909 }
7910
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007911 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007912 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007913 if (!voice_extn_is_compress_voip_supported()) {
7914 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7915 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007916 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307917 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007918 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7919 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007920 out->volume_l = INVALID_OUT_VOLUME;
7921 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007922
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007923 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007924 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007925 uint32_t channel_count =
7926 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307927 out->config.channels = channel_count;
7928
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007929 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7930 out->sample_rate, out->format,
7931 channel_count, false);
7932 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7933 if (frame_size != 0)
7934 out->config.period_size = buffer_size / frame_size;
7935 else
7936 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007937 }
7938 } else {
7939 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7940 voice_extn_compress_voip_is_active(out->dev)) &&
7941 (voice_extn_compress_voip_is_config_supported(config))) {
7942 ret = voice_extn_compress_voip_open_output_stream(out);
7943 if (ret != 0) {
7944 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7945 __func__, ret);
7946 goto error_open;
7947 }
Sujin Panicker19027262019-09-16 18:28:06 +05307948 } else {
7949 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7950 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007951 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007952 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007953 } else if (audio_is_linear_pcm(out->format) &&
7954 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7955 out->channel_mask = config->channel_mask;
7956 out->sample_rate = config->sample_rate;
7957 out->format = config->format;
7958 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7959 // does this change?
7960 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7961 out->config.rate = config->sample_rate;
7962 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7963 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7964 audio_bytes_per_sample(config->format));
7965 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007966 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307967 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307968 pthread_mutex_lock(&adev->lock);
7969 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7970 pthread_mutex_unlock(&adev->lock);
7971
7972 // reject offload during card offline to allow
7973 // fallback to s/w paths
7974 if (offline) {
7975 ret = -ENODEV;
7976 goto error_open;
7977 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007978
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007979 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7980 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7981 ALOGE("%s: Unsupported Offload information", __func__);
7982 ret = -EINVAL;
7983 goto error_open;
7984 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007985
Atul Khare3fa6e542017-08-09 00:56:17 +05307986 if (config->offload_info.format == 0)
7987 config->offload_info.format = config->format;
7988 if (config->offload_info.sample_rate == 0)
7989 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007990
Mingming Yin90310102013-11-13 16:57:00 -08007991 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307992 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007993 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007994 ret = -EINVAL;
7995 goto error_open;
7996 }
7997
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007998 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7999 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8000 (audio_extn_passthru_is_passthrough_stream(out)) &&
8001 !((config->sample_rate == 48000) ||
8002 (config->sample_rate == 96000) ||
8003 (config->sample_rate == 192000))) {
8004 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8005 __func__, config->sample_rate, config->offload_info.format);
8006 ret = -EINVAL;
8007 goto error_open;
8008 }
8009
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008010 out->compr_config.codec = (struct snd_codec *)
8011 calloc(1, sizeof(struct snd_codec));
8012
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008013 if (!out->compr_config.codec) {
8014 ret = -ENOMEM;
8015 goto error_open;
8016 }
8017
Dhananjay Kumarac341582017-02-23 23:42:25 +05308018 out->stream.pause = out_pause;
8019 out->stream.resume = out_resume;
8020 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308021 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308022 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008023 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308024 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008025 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308026 } else {
8027 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8028 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008029 }
vivek mehta446c3962015-09-14 10:57:35 -07008030
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308031 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8032 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008033#ifdef AUDIO_GKI_ENABLED
8034 /* out->compr_config.codec->reserved[1] is for flags */
8035 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8036#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308037 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008038#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308039 }
8040
vivek mehta446c3962015-09-14 10:57:35 -07008041 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008042 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008043 config->format == 0 && config->sample_rate == 0 &&
8044 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008045 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008046 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8047 } else {
8048 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8049 ret = -EEXIST;
8050 goto error_open;
8051 }
vivek mehta446c3962015-09-14 10:57:35 -07008052 }
8053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054 if (config->offload_info.channel_mask)
8055 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008056 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008057 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008058 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008059 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308060 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008061 ret = -EINVAL;
8062 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008063 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008064
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008065 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008066 out->sample_rate = config->offload_info.sample_rate;
8067
Mingming Yin3ee55c62014-08-04 14:23:35 -07008068 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008069
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308070 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308071 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308072 audio_extn_dolby_send_ddp_endp_params(adev);
8073 audio_extn_dolby_set_dmid(adev);
8074 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008076 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008077 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008078 out->compr_config.codec->bit_rate =
8079 config->offload_info.bit_rate;
8080 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308081 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008082 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308083 /* Update bit width only for non passthrough usecases.
8084 * For passthrough usecases, the output will always be opened @16 bit
8085 */
8086 if (!audio_extn_passthru_is_passthrough_stream(out))
8087 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308088
8089 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008090#ifdef AUDIO_GKI_ENABLED
8091 /* out->compr_config.codec->reserved[1] is for flags */
8092 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8093 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8094#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308095 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8096 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008097#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308098
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008099 /*TODO: Do we need to change it for passthrough */
8100 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008101
Manish Dewangana6fc5442015-08-24 20:30:31 +05308102 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8103 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308104 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308105 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308106 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8107 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308108
8109 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8110 AUDIO_FORMAT_PCM) {
8111
8112 /*Based on platform support, configure appropriate alsa format for corresponding
8113 *hal input format.
8114 */
8115 out->compr_config.codec->format = hal_format_to_alsa(
8116 config->offload_info.format);
8117
Ashish Jain83a6cc22016-06-28 14:34:17 +05308118 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308119 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308120 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308121
Dhananjay Kumarac341582017-02-23 23:42:25 +05308122 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308123 *hal input format and alsa format might differ based on platform support.
8124 */
8125 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308126 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308127
8128 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8129
Deeraj Soman93155a62019-09-30 19:00:37 +05308130 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8131 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8132 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8133 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8134 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308135
Ashish Jainf1eaa582016-05-23 20:54:24 +05308136 /* Check if alsa session is configured with the same format as HAL input format,
8137 * if not then derive correct fragment size needed to accomodate the
8138 * conversion of HAL input format to alsa format.
8139 */
8140 audio_extn_utils_update_direct_pcm_fragment_size(out);
8141
8142 /*if hal input and output fragment size is different this indicates HAL input format is
8143 *not same as the alsa format
8144 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308145 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308146 /*Allocate a buffer to convert input data to the alsa configured format.
8147 *size of convert buffer is equal to the size required to hold one fragment size
8148 *worth of pcm data, this is because flinger does not write more than fragment_size
8149 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308150 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8151 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308152 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8153 ret = -ENOMEM;
8154 goto error_open;
8155 }
8156 }
8157 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8158 out->compr_config.fragment_size =
8159 audio_extn_passthru_get_buffer_size(&config->offload_info);
8160 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8161 } else {
8162 out->compr_config.fragment_size =
8163 platform_get_compress_offload_buffer_size(&config->offload_info);
8164 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8165 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008166
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308167 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8168 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8169 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008170 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8171#ifdef AUDIO_GKI_ENABLED
8172 generic_dec =
8173 &(out->compr_config.codec->options.generic.reserved[1]);
8174 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8175 AUDIO_OUTPUT_BIT_WIDTH;
8176#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308177 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008178#endif
8179 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008180
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308181 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8182 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8183 }
8184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008185 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8186 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008187
Manish Dewangan69426c82017-01-30 17:35:36 +05308188 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8189 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8190 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8191 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8192 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8193 } else {
8194 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8195 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008196
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308197 memset(&out->channel_map_param, 0,
8198 sizeof(struct audio_out_channel_map_param));
8199
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008200 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308201 out->send_next_track_params = false;
8202 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008203 out->offload_state = OFFLOAD_STATE_IDLE;
8204 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008205 out->writeAt.tv_sec = 0;
8206 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008207
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008208 audio_extn_dts_create_state_notifier_node(out->usecase);
8209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008210 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8211 __func__, config->offload_info.version,
8212 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308213
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308214 /* Check if DSD audio format is supported in codec
8215 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308216 */
8217
8218 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308219 (!platform_check_codec_dsd_support(adev->platform) ||
8220 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308221 ret = -EINVAL;
8222 goto error_open;
8223 }
8224
Ashish Jain5106d362016-05-11 19:23:33 +05308225 /* Disable gapless if any of the following is true
8226 * passthrough playback
8227 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308228 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308229 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308230 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308231 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008232 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308233 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308234 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308235 check_and_set_gapless_mode(adev, false);
8236 } else
8237 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008238
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308239 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008240 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8241 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308242 if (config->format == AUDIO_FORMAT_DSD) {
8243 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008244#ifdef AUDIO_GKI_ENABLED
8245 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8246 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8247#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308248 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008249#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308250 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008251
8252 create_offload_callback_thread(out);
8253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008254 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008255 switch (config->sample_rate) {
8256 case 0:
8257 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8258 break;
8259 case 8000:
8260 case 16000:
8261 case 48000:
8262 out->sample_rate = config->sample_rate;
8263 break;
8264 default:
8265 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8266 config->sample_rate);
8267 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8268 ret = -EINVAL;
8269 goto error_open;
8270 }
8271 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8272 switch (config->channel_mask) {
8273 case AUDIO_CHANNEL_NONE:
8274 case AUDIO_CHANNEL_OUT_STEREO:
8275 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8276 break;
8277 default:
8278 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8279 config->channel_mask);
8280 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8281 ret = -EINVAL;
8282 goto error_open;
8283 }
8284 switch (config->format) {
8285 case AUDIO_FORMAT_DEFAULT:
8286 case AUDIO_FORMAT_PCM_16_BIT:
8287 out->format = AUDIO_FORMAT_PCM_16_BIT;
8288 break;
8289 default:
8290 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8291 config->format);
8292 config->format = AUDIO_FORMAT_PCM_16_BIT;
8293 ret = -EINVAL;
8294 goto error_open;
8295 }
8296
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308297 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008298 if (ret != 0) {
8299 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008300 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008301 goto error_open;
8302 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008303 } else if (is_single_device_type_equal(&out->device_list,
8304 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008305 switch (config->sample_rate) {
8306 case 0:
8307 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8308 break;
8309 case 8000:
8310 case 16000:
8311 case 48000:
8312 out->sample_rate = config->sample_rate;
8313 break;
8314 default:
8315 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8316 config->sample_rate);
8317 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8318 ret = -EINVAL;
8319 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008320 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008321 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8322 switch (config->channel_mask) {
8323 case AUDIO_CHANNEL_NONE:
8324 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8325 break;
8326 case AUDIO_CHANNEL_OUT_STEREO:
8327 out->channel_mask = config->channel_mask;
8328 break;
8329 default:
8330 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8331 config->channel_mask);
8332 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8333 ret = -EINVAL;
8334 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008335 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008336 switch (config->format) {
8337 case AUDIO_FORMAT_DEFAULT:
8338 out->format = AUDIO_FORMAT_PCM_16_BIT;
8339 break;
8340 case AUDIO_FORMAT_PCM_16_BIT:
8341 out->format = config->format;
8342 break;
8343 default:
8344 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8345 config->format);
8346 config->format = AUDIO_FORMAT_PCM_16_BIT;
8347 ret = -EINVAL;
8348 break;
8349 }
8350 if (ret != 0)
8351 goto error_open;
8352
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008353 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8354 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008355 out->config.rate = out->sample_rate;
8356 out->config.channels =
8357 audio_channel_count_from_out_mask(out->channel_mask);
8358 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008359 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008360 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308361 unsigned int channels = 0;
8362 /*Update config params to default if not set by the caller*/
8363 if (config->sample_rate == 0)
8364 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8365 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8366 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8367 if (config->format == AUDIO_FORMAT_DEFAULT)
8368 config->format = AUDIO_FORMAT_PCM_16_BIT;
8369
8370 channels = audio_channel_count_from_out_mask(out->channel_mask);
8371
Varun Balaraje49253e2017-07-06 19:48:56 +05308372 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8373 out->usecase = get_interactive_usecase(adev);
8374 out->config = pcm_config_low_latency;
8375 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308376 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008377 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8378 out->flags);
8379 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008380 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8381 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8382 out->config = pcm_config_mmap_playback;
8383 out->stream.start = out_start;
8384 out->stream.stop = out_stop;
8385 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8386 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308387 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8388 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008389 out->hal_output_suspend_supported =
8390 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8391 out->dynamic_pm_qos_config_supported =
8392 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8393 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008394 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8395 } else {
8396 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8397 //the mixer path will be a string similar to "low-latency-playback resume"
8398 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8399 strlcat(out->pm_qos_mixer_path,
8400 " resume", MAX_MIXER_PATH_LEN);
8401 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8402 out->pm_qos_mixer_path);
8403 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308404 out->config = pcm_config_low_latency;
8405 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8406 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8407 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308408 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8409 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8410 if (out->config.period_size <= 0) {
8411 ALOGE("Invalid configuration period size is not valid");
8412 ret = -EINVAL;
8413 goto error_open;
8414 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008415 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8416 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8417 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008418 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8419 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8420 out->config = pcm_config_haptics_audio;
8421 if (force_haptic_path)
8422 adev->haptics_config = pcm_config_haptics_audio;
8423 else
8424 adev->haptics_config = pcm_config_haptics;
8425
Meng Wangd08ce322020-04-02 08:59:20 +08008426 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008427 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8428
8429 if (force_haptic_path) {
8430 out->config.channels = 1;
8431 adev->haptics_config.channels = 1;
8432 } else
8433 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 -08008434 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008435 ret = audio_extn_auto_hal_open_output_stream(out);
8436 if (ret) {
8437 ALOGE("%s: Failed to open output stream for bus device", __func__);
8438 ret = -EINVAL;
8439 goto error_open;
8440 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308441 } else {
8442 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008443 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8444 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308445 }
8446 out->hal_ip_format = format = out->format;
8447 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8448 out->hal_op_format = pcm_format_to_hal(out->config.format);
8449 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8450 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008451 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308452 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308453 if (out->hal_ip_format != out->hal_op_format) {
8454 uint32_t buffer_size = out->config.period_size *
8455 format_to_bitwidth_table[out->hal_op_format] *
8456 out->config.channels;
8457 out->convert_buffer = calloc(1, buffer_size);
8458 if (out->convert_buffer == NULL){
8459 ALOGE("Allocation failed for convert buffer for size %d",
8460 out->compr_config.fragment_size);
8461 ret = -ENOMEM;
8462 goto error_open;
8463 }
8464 ALOGD("Convert buffer allocated of size %d", buffer_size);
8465 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008466 }
8467
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008468 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8469 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308470
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008471 /* TODO remove this hardcoding and check why width is zero*/
8472 if (out->bit_width == 0)
8473 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308474 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008475 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008476 &out->device_list, out->flags,
8477 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308478 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308479 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008480 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008481 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8482 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008483 if(adev->primary_output == NULL)
8484 adev->primary_output = out;
8485 else {
8486 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008487 ret = -EEXIST;
8488 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008489 }
8490 }
8491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008492 /* Check if this usecase is already existing */
8493 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008494 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8495 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008497 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008498 ret = -EEXIST;
8499 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008500 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008502 pthread_mutex_unlock(&adev->lock);
8503
8504 out->stream.common.get_sample_rate = out_get_sample_rate;
8505 out->stream.common.set_sample_rate = out_set_sample_rate;
8506 out->stream.common.get_buffer_size = out_get_buffer_size;
8507 out->stream.common.get_channels = out_get_channels;
8508 out->stream.common.get_format = out_get_format;
8509 out->stream.common.set_format = out_set_format;
8510 out->stream.common.standby = out_standby;
8511 out->stream.common.dump = out_dump;
8512 out->stream.common.set_parameters = out_set_parameters;
8513 out->stream.common.get_parameters = out_get_parameters;
8514 out->stream.common.add_audio_effect = out_add_audio_effect;
8515 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8516 out->stream.get_latency = out_get_latency;
8517 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008518#ifdef NO_AUDIO_OUT
8519 out->stream.write = out_write_for_no_output;
8520#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008521 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008522#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008523 out->stream.get_render_position = out_get_render_position;
8524 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008525 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008526
Haynes Mathew George16081042017-05-31 17:16:49 -07008527 if (out->realtime)
8528 out->af_period_multiplier = af_period_multiplier;
8529 else
8530 out->af_period_multiplier = 1;
8531
Andy Hunga1f48fa2019-07-01 18:14:53 -07008532 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008535 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008536 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008537
8538 config->format = out->stream.common.get_format(&out->stream.common);
8539 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8540 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308541 register_format(out->format, out->supported_formats);
8542 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8543 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008544
Aalique Grahame22e49102018-12-18 14:23:57 -08008545 out->error_log = error_log_create(
8546 ERROR_LOG_ENTRIES,
8547 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8548
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308549 /*
8550 By locking output stream before registering, we allow the callback
8551 to update stream's state only after stream's initial state is set to
8552 adev state.
8553 */
8554 lock_output_stream(out);
8555 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8556 pthread_mutex_lock(&adev->lock);
8557 out->card_status = adev->card_status;
8558 pthread_mutex_unlock(&adev->lock);
8559 pthread_mutex_unlock(&out->lock);
8560
Aalique Grahame22e49102018-12-18 14:23:57 -08008561 stream_app_type_cfg_init(&out->app_type_cfg);
8562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008563 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308564 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008565 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008566
8567 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8568 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8569 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008570 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308571 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008572 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008573 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308574 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8575 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008576 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8577 out->usecase, PCM_PLAYBACK);
8578 hdlr_stream_cfg.flags = out->flags;
8579 hdlr_stream_cfg.type = PCM_PLAYBACK;
8580 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8581 &hdlr_stream_cfg);
8582 if (ret) {
8583 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8584 out->adsp_hdlr_stream_handle = NULL;
8585 }
8586 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308587 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8588 is_direct_passthough, false);
8589 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8590 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008591 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008592 if (ret < 0) {
8593 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8594 out->ip_hdlr_handle = NULL;
8595 }
8596 }
Derek Chenf939fb72018-11-13 13:34:41 -08008597
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008598 ret = io_streams_map_insert(adev, &out->stream.common,
8599 out->handle, AUDIO_PATCH_HANDLE_NONE);
8600 if (ret != 0)
8601 goto error_open;
8602
Derek Chenf939fb72018-11-13 13:34:41 -08008603 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8604 calloc(1, sizeof(streams_output_ctxt_t));
8605 if (out_ctxt == NULL) {
8606 ALOGE("%s fail to allocate output ctxt", __func__);
8607 ret = -ENOMEM;
8608 goto error_open;
8609 }
8610 out_ctxt->output = out;
8611
8612 pthread_mutex_lock(&adev->lock);
8613 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8614 pthread_mutex_unlock(&adev->lock);
8615
Eric Laurent994a6932013-07-17 11:51:42 -07008616 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008617 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008618
8619error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308620 if (out->convert_buffer)
8621 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008622 free(out);
8623 *stream_out = NULL;
8624 ALOGD("%s: exit: ret %d", __func__, ret);
8625 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008626}
8627
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308628void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008629 struct audio_stream_out *stream)
8630{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008631 struct stream_out *out = (struct stream_out *)stream;
8632 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008633 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008634
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008635 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308636
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008637 io_streams_map_remove(adev, out->handle);
8638
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308639 // must deregister from sndmonitor first to prevent races
8640 // between the callback and close_stream
8641 audio_extn_snd_mon_unregister_listener(out);
8642
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008643 /* close adsp hdrl session before standby */
8644 if (out->adsp_hdlr_stream_handle) {
8645 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8646 if (ret)
8647 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8648 out->adsp_hdlr_stream_handle = NULL;
8649 }
8650
Manish Dewangan21a850a2017-08-14 12:03:55 +05308651 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008652 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8653 out->ip_hdlr_handle = NULL;
8654 }
8655
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008656 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308657 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008658 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308659 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308660 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008661 if(ret != 0)
8662 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8663 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008664 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008665 out_standby(&stream->common);
8666
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008667 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008668 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008669 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008670 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008671 if (out->compr_config.codec != NULL)
8672 free(out->compr_config.codec);
8673 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008674
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308675 out->a2dp_compress_mute = false;
8676
Varun Balaraje49253e2017-07-06 19:48:56 +05308677 if (is_interactive_usecase(out->usecase))
8678 free_interactive_usecase(adev, out->usecase);
8679
Ashish Jain83a6cc22016-06-28 14:34:17 +05308680 if (out->convert_buffer != NULL) {
8681 free(out->convert_buffer);
8682 out->convert_buffer = NULL;
8683 }
8684
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008685 if (adev->voice_tx_output == out)
8686 adev->voice_tx_output = NULL;
8687
Aalique Grahame22e49102018-12-18 14:23:57 -08008688 error_log_destroy(out->error_log);
8689 out->error_log = NULL;
8690
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308691 if (adev->primary_output == out)
8692 adev->primary_output = NULL;
8693
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008694 pthread_cond_destroy(&out->cond);
8695 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008696 pthread_mutex_destroy(&out->pre_lock);
8697 pthread_mutex_destroy(&out->latch_lock);
8698 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008699
8700 pthread_mutex_lock(&adev->lock);
8701 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8702 if (out_ctxt != NULL) {
8703 list_remove(&out_ctxt->list);
8704 free(out_ctxt);
8705 } else {
8706 ALOGW("%s, output stream already closed", __func__);
8707 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008708 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008709 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008710 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008711}
8712
8713static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8714{
8715 struct audio_device *adev = (struct audio_device *)dev;
8716 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008717 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008718 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008719 int ret;
8720 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008721 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008722 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008723 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008724
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008725 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008726 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008727
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308728 if (!parms)
8729 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308730
Derek Chen6f293672019-04-01 01:40:24 -07008731 /* notify adev and input/output streams on the snd card status */
8732 adev_snd_mon_cb((void *)adev, parms);
8733
8734 list_for_each(node, &adev->active_outputs_list) {
8735 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8736 streams_output_ctxt_t,
8737 list);
8738 out_snd_mon_cb((void *)out_ctxt->output, parms);
8739 }
8740
8741 list_for_each(node, &adev->active_inputs_list) {
8742 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8743 streams_input_ctxt_t,
8744 list);
8745 in_snd_mon_cb((void *)in_ctxt->input, parms);
8746 }
8747
Zhou Songd6d71752019-05-21 18:08:51 +08008748 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308749 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8750 if (ret >= 0) {
8751 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008752 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308753 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008754 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308755 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008756 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008757 }
8758 }
8759
8760 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008761 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008762 if (!strncmp(value, "false", 5) &&
8763 audio_extn_a2dp_source_is_suspended()) {
8764 struct audio_usecase *usecase;
8765 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008766 list_for_each(node, &adev->usecase_list) {
8767 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008768 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008769 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008770 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008771 reassign_device_list(&usecase->stream.in->device_list,
8772 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008773 select_devices(adev, usecase->id);
8774 }
Zhou Songd6d71752019-05-21 18:08:51 +08008775 }
8776 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308777 }
8778
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008779 status = voice_set_parameters(adev, parms);
8780 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008781 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008783 status = platform_set_parameters(adev->platform, parms);
8784 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008785 goto done;
8786
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008787 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8788 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008789 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008790 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8791 adev->bluetooth_nrec = true;
8792 else
8793 adev->bluetooth_nrec = false;
8794 }
8795
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008796 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8797 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008798 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8799 adev->screen_off = false;
8800 else
8801 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008802 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008803 }
8804
Eric Laurent4b084132018-10-19 17:33:43 -07008805 ret = str_parms_get_int(parms, "rotation", &val);
8806 if (ret >= 0) {
8807 bool reverse_speakers = false;
8808 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8809 switch (val) {
8810 // FIXME: note that the code below assumes that the speakers are in the correct placement
8811 // relative to the user when the device is rotated 90deg from its default rotation. This
8812 // assumption is device-specific, not platform-specific like this code.
8813 case 270:
8814 reverse_speakers = true;
8815 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8816 break;
8817 case 0:
8818 case 180:
8819 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8820 break;
8821 case 90:
8822 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8823 break;
8824 default:
8825 ALOGE("%s: unexpected rotation of %d", __func__, val);
8826 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008827 }
Eric Laurent4b084132018-10-19 17:33:43 -07008828 if (status == 0) {
8829 // check and set swap
8830 // - check if orientation changed and speaker active
8831 // - set rotation and cache the rotation value
8832 adev->camera_orientation =
8833 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8834 if (!audio_extn_is_maxx_audio_enabled())
8835 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8836 }
8837 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008838
Mingming Yin514a8bc2014-07-29 15:22:21 -07008839 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8840 if (ret >= 0) {
8841 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8842 adev->bt_wb_speech_enabled = true;
8843 else
8844 adev->bt_wb_speech_enabled = false;
8845 }
8846
Zhou Song12c29502019-03-16 10:37:18 +08008847 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8848 if (ret >= 0) {
8849 val = atoi(value);
8850 adev->swb_speech_mode = val;
8851 }
8852
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008853 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8854 if (ret >= 0) {
8855 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308856 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008857 if (audio_is_output_device(val) &&
8858 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008859 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008860 platform_get_controller_stream_from_params(parms, &controller, &stream);
8861 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8862 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008863 if (ret < 0) {
8864 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308865 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008866 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008867 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308868 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008869 /*
8870 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8871 * Per AudioPolicyManager, USB device is higher priority than WFD.
8872 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8873 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8874 * starting voice call on USB
8875 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008876 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308877 if (ret >= 0)
8878 audio_extn_usb_add_device(device, atoi(value));
8879
Zhou Song6f862822017-11-06 17:27:57 +08008880 if (!audio_extn_usb_is_tunnel_supported()) {
8881 ALOGV("detected USB connect .. disable proxy");
8882 adev->allow_afe_proxy_usage = false;
8883 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008884 }
8885 }
8886
8887 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8888 if (ret >= 0) {
8889 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308890 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008891 /*
8892 * The HDMI / Displayport disconnect handling has been moved to
8893 * audio extension to ensure that its parameters are not
8894 * invalidated prior to updating sysfs of the disconnect event
8895 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8896 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308897 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008898 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308899 if (ret >= 0)
8900 audio_extn_usb_remove_device(device, atoi(value));
8901
Zhou Song6f862822017-11-06 17:27:57 +08008902 if (!audio_extn_usb_is_tunnel_supported()) {
8903 ALOGV("detected USB disconnect .. enable proxy");
8904 adev->allow_afe_proxy_usage = true;
8905 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008906 }
8907 }
8908
Aalique Grahame22e49102018-12-18 14:23:57 -08008909 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008910 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008911
8912 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008913 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308914 struct audio_usecase *usecase;
8915 struct listnode *node;
8916 list_for_each(node, &adev->usecase_list) {
8917 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008918 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8919 continue;
8920
8921 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308922 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308923 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308924 ALOGD("Switching to speaker and muting the stream before select_devices");
8925 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308926 //force device switch to re configure encoder
8927 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308928 ALOGD("Unmuting the stream after select_devices");
Weiyin Jiang280ea742020-09-08 20:28:22 +08008929 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308930 usecase->stream.out->a2dp_compress_mute = false;
Weiyin Jiang280ea742020-09-08 20:28:22 +08008931 out_set_compr_volume(&usecase->stream.out->stream,
8932 usecase->stream.out->volume_l,
8933 usecase->stream.out->volume_r);
8934 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308935 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308936 break;
Weiyin Jiang280ea742020-09-08 20:28:22 +08008937 } else if (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
8938 pthread_mutex_lock(&usecase->stream.out->latch_lock);
8939 if (usecase->stream.out->a2dp_compress_mute) {
8940 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8941 reassign_device_list(&usecase->stream.out->device_list,
8942 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8943 check_a2dp_restore_l(adev, usecase->stream.out, true);
8944 break;
8945 }
8946 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308947 }
8948 }
8949 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008950
8951 //handle vr audio setparam
8952 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8953 value, sizeof(value));
8954 if (ret >= 0) {
8955 ALOGI("Setting vr mode to be %s", value);
8956 if (!strncmp(value, "true", 4)) {
8957 adev->vr_audio_mode_enabled = true;
8958 ALOGI("Setting vr mode to true");
8959 } else if (!strncmp(value, "false", 5)) {
8960 adev->vr_audio_mode_enabled = false;
8961 ALOGI("Setting vr mode to false");
8962 } else {
8963 ALOGI("wrong vr mode set");
8964 }
8965 }
8966
Eric Laurent4b084132018-10-19 17:33:43 -07008967 //FIXME: to be replaced by proper video capture properties API
8968 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8969 if (ret >= 0) {
8970 int camera_facing = CAMERA_FACING_BACK;
8971 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8972 camera_facing = CAMERA_FACING_FRONT;
8973 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8974 camera_facing = CAMERA_FACING_BACK;
8975 else {
8976 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8977 goto done;
8978 }
8979 adev->camera_orientation =
8980 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8981 struct audio_usecase *usecase;
8982 struct listnode *node;
8983 list_for_each(node, &adev->usecase_list) {
8984 usecase = node_to_item(node, struct audio_usecase, list);
8985 struct stream_in *in = usecase->stream.in;
8986 if (usecase->type == PCM_CAPTURE && in != NULL &&
8987 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8988 select_devices(adev, in->usecase);
8989 }
8990 }
8991 }
8992
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308993 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008994done:
8995 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008996 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308997error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008998 ALOGV("%s: exit with code(%d)", __func__, status);
8999 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009000}
9001
9002static char* adev_get_parameters(const struct audio_hw_device *dev,
9003 const char *keys)
9004{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309005 ALOGD("%s:%s", __func__, keys);
9006
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009007 struct audio_device *adev = (struct audio_device *)dev;
9008 struct str_parms *reply = str_parms_create();
9009 struct str_parms *query = str_parms_create_str(keys);
9010 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309011 char value[256] = {0};
9012 int ret = 0;
9013
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009014 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009015 if (reply) {
9016 str_parms_destroy(reply);
9017 }
9018 if (query) {
9019 str_parms_destroy(query);
9020 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009021 ALOGE("adev_get_parameters: failed to create query or reply");
9022 return NULL;
9023 }
9024
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009025 //handle vr audio getparam
9026
9027 ret = str_parms_get_str(query,
9028 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9029 value, sizeof(value));
9030
9031 if (ret >= 0) {
9032 bool vr_audio_enabled = false;
9033 pthread_mutex_lock(&adev->lock);
9034 vr_audio_enabled = adev->vr_audio_mode_enabled;
9035 pthread_mutex_unlock(&adev->lock);
9036
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009037 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009038
9039 if (vr_audio_enabled) {
9040 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9041 "true");
9042 goto exit;
9043 } else {
9044 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9045 "false");
9046 goto exit;
9047 }
9048 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009049
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009050 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009051 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009052 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009053 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009054 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009055 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309056 pthread_mutex_unlock(&adev->lock);
9057
Naresh Tannirud7205b62014-06-20 02:54:48 +05309058exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009059 str = str_parms_to_str(reply);
9060 str_parms_destroy(query);
9061 str_parms_destroy(reply);
9062
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009063 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009064 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009065}
9066
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009067static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009068{
9069 return 0;
9070}
9071
9072static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9073{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009074 int ret;
9075 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009076
9077 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9078
Haynes Mathew George5191a852013-09-11 14:19:36 -07009079 pthread_mutex_lock(&adev->lock);
9080 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009081 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009082 pthread_mutex_unlock(&adev->lock);
9083 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009084}
9085
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009086static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9087 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009088{
9089 return -ENOSYS;
9090}
9091
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009092static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9093 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009094{
9095 return -ENOSYS;
9096}
9097
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009098static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9099 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009100{
9101 return -ENOSYS;
9102}
9103
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009104static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9105 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009106{
9107 return -ENOSYS;
9108}
9109
9110static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9111{
9112 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009113 struct listnode *node;
9114 struct audio_usecase *usecase = NULL;
9115 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009117 pthread_mutex_lock(&adev->lock);
9118 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309119 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9120 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309122 if( mode == AUDIO_MODE_CALL_SCREEN ){
9123 adev->current_call_output = adev->primary_output;
9124 voice_start_call(adev);
9125 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009126 (mode == AUDIO_MODE_NORMAL ||
9127 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009128 list_for_each(node, &adev->usecase_list) {
9129 usecase = node_to_item(node, struct audio_usecase, list);
9130 if (usecase->type == VOICE_CALL)
9131 break;
9132 }
9133 if (usecase &&
9134 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9135 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9136 true);
9137 if (ret != 0) {
9138 /* default service interval was successfully updated,
9139 reopen USB backend with new service interval */
9140 check_usecases_codec_backend(adev,
9141 usecase,
9142 usecase->out_snd_device);
9143 }
9144 }
9145
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009146 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009147 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009148 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009149 // restore device for other active usecases after stop call
9150 list_for_each(node, &adev->usecase_list) {
9151 usecase = node_to_item(node, struct audio_usecase, list);
9152 select_devices(adev, usecase->id);
9153 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009155 }
9156 pthread_mutex_unlock(&adev->lock);
9157 return 0;
9158}
9159
9160static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9161{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009162 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009163 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009164
9165 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009166 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009167 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009168
Derek Chend2530072014-11-24 12:39:14 -08009169 if (adev->ext_hw_plugin)
9170 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009171
9172 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009173 pthread_mutex_unlock(&adev->lock);
9174
9175 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176}
9177
9178static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9179{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009180 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009181 return 0;
9182}
9183
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009184static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009185 const struct audio_config *config)
9186{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009187 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009188
Aalique Grahame22e49102018-12-18 14:23:57 -08009189 /* Don't know if USB HIFI in this context so use true to be conservative */
9190 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9191 true /*is_usb_hifi */) != 0)
9192 return 0;
9193
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009194 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9195 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009196}
9197
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009198static bool adev_input_allow_hifi_record(struct audio_device *adev,
9199 audio_devices_t devices,
9200 audio_input_flags_t flags,
9201 audio_source_t source) {
9202 const bool allowed = true;
9203
9204 if (!audio_is_usb_in_device(devices))
9205 return !allowed;
9206
9207 switch (flags) {
9208 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009209 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009210 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9211 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009212 default:
9213 return !allowed;
9214 }
9215
9216 switch (source) {
9217 case AUDIO_SOURCE_DEFAULT:
9218 case AUDIO_SOURCE_MIC:
9219 case AUDIO_SOURCE_UNPROCESSED:
9220 break;
9221 default:
9222 return !allowed;
9223 }
9224
9225 switch (adev->mode) {
9226 case 0:
9227 break;
9228 default:
9229 return !allowed;
9230 }
9231
9232 return allowed;
9233}
9234
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009235static int adev_update_voice_comm_input_stream(struct stream_in *in,
9236 struct audio_config *config)
9237{
9238 bool valid_rate = (config->sample_rate == 8000 ||
9239 config->sample_rate == 16000 ||
9240 config->sample_rate == 32000 ||
9241 config->sample_rate == 48000);
9242 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9243
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009244 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009245 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009246 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9247 in->config = default_pcm_config_voip_copp;
9248 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9249 DEFAULT_VOIP_BUF_DURATION_MS,
9250 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009251 } else {
9252 ALOGW("%s No valid input in voip, use defaults"
9253 "sample rate %u, channel mask 0x%X",
9254 __func__, config->sample_rate, in->channel_mask);
9255 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009256 in->config.rate = config->sample_rate;
9257 in->sample_rate = config->sample_rate;
9258 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009259 //XXX needed for voice_extn_compress_voip_open_input_stream
9260 in->config.rate = config->sample_rate;
9261 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309262 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009263 voice_extn_compress_voip_is_active(in->dev)) &&
9264 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9265 valid_rate && valid_ch) {
9266 voice_extn_compress_voip_open_input_stream(in);
9267 // update rate entries to match config from AF
9268 in->config.rate = config->sample_rate;
9269 in->sample_rate = config->sample_rate;
9270 } else {
9271 ALOGW("%s compress voip not active, use defaults", __func__);
9272 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009273 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009274 return 0;
9275}
9276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009277static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009278 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009279 audio_devices_t devices,
9280 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009281 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309282 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009283 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009284 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009285{
9286 struct audio_device *adev = (struct audio_device *)dev;
9287 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009288 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009289 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009290 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309291 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009292 bool is_usb_dev = audio_is_usb_in_device(devices);
9293 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9294 devices,
9295 flags,
9296 source);
Andy Hung94320602018-10-29 18:31:12 -07009297 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9298 " sample_rate %u, channel_mask %#x, format %#x",
9299 __func__, flags, is_usb_dev, may_use_hifi_record,
9300 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309301
kunleizdff872d2018-08-20 14:40:33 +08009302 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009303 is_usb_dev = false;
9304 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9305 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9306 __func__, devices);
9307 }
9308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009309 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009310
9311 if (!(is_usb_dev && may_use_hifi_record)) {
9312 if (config->sample_rate == 0)
9313 config->sample_rate = 48000;
9314 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9315 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9316 if (config->format == AUDIO_FORMAT_DEFAULT)
9317 config->format = AUDIO_FORMAT_PCM_16_BIT;
9318
9319 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9320
Aalique Grahame22e49102018-12-18 14:23:57 -08009321 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9322 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009323 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009325
Rahul Sharma99770982019-03-06 17:05:26 +05309326 pthread_mutex_lock(&adev->lock);
9327 if (in_get_stream(adev, handle) != NULL) {
9328 ALOGW("%s, input stream already opened", __func__);
9329 ret = -EEXIST;
9330 }
9331 pthread_mutex_unlock(&adev->lock);
9332 if (ret)
9333 return ret;
9334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009335 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009336
9337 if (!in) {
9338 ALOGE("failed to allocate input stream");
9339 return -ENOMEM;
9340 }
9341
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309342 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309343 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9344 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009345 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009346 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009348 in->stream.common.get_sample_rate = in_get_sample_rate;
9349 in->stream.common.set_sample_rate = in_set_sample_rate;
9350 in->stream.common.get_buffer_size = in_get_buffer_size;
9351 in->stream.common.get_channels = in_get_channels;
9352 in->stream.common.get_format = in_get_format;
9353 in->stream.common.set_format = in_set_format;
9354 in->stream.common.standby = in_standby;
9355 in->stream.common.dump = in_dump;
9356 in->stream.common.set_parameters = in_set_parameters;
9357 in->stream.common.get_parameters = in_get_parameters;
9358 in->stream.common.add_audio_effect = in_add_audio_effect;
9359 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9360 in->stream.set_gain = in_set_gain;
9361 in->stream.read = in_read;
9362 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009363 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309364 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009365 in->stream.set_microphone_direction = in_set_microphone_direction;
9366 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009367 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009368
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009369 list_init(&in->device_list);
9370 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009371 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009372 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009373 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009374 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009375 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009376 in->bit_width = 16;
9377 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009378 in->direction = MIC_DIRECTION_UNSPECIFIED;
9379 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009380 list_init(&in->aec_list);
9381 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009382 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009383
Andy Hung94320602018-10-29 18:31:12 -07009384 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009385 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9386 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9387 /* Force channel config requested to mono if incall
9388 record is being requested for only uplink/downlink */
9389 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9390 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9391 ret = -EINVAL;
9392 goto err_open;
9393 }
9394 }
9395
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009396 if (is_usb_dev && may_use_hifi_record) {
9397 /* HiFi record selects an appropriate format, channel, rate combo
9398 depending on sink capabilities*/
9399 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9400 &config->format,
9401 &in->supported_formats[0],
9402 MAX_SUPPORTED_FORMATS,
9403 &config->channel_mask,
9404 &in->supported_channel_masks[0],
9405 MAX_SUPPORTED_CHANNEL_MASKS,
9406 &config->sample_rate,
9407 &in->supported_sample_rates[0],
9408 MAX_SUPPORTED_SAMPLE_RATES);
9409 if (ret != 0) {
9410 ret = -EINVAL;
9411 goto err_open;
9412 }
9413 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009414 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309415 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309416 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9417 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9418 in->config.format = PCM_FORMAT_S32_LE;
9419 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309420 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9421 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9422 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9423 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9424 bool ret_error = false;
9425 in->bit_width = 24;
9426 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9427 from HAL is 24_packed and 8_24
9428 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9429 24_packed return error indicating supported format is 24_packed
9430 *> In case of any other source requesting 24 bit or float return error
9431 indicating format supported is 16 bit only.
9432
9433 on error flinger will retry with supported format passed
9434 */
9435 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9436 (source != AUDIO_SOURCE_CAMCORDER)) {
9437 config->format = AUDIO_FORMAT_PCM_16_BIT;
9438 if (config->sample_rate > 48000)
9439 config->sample_rate = 48000;
9440 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009441 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9442 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309443 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9444 ret_error = true;
9445 }
9446
9447 if (ret_error) {
9448 ret = -EINVAL;
9449 goto err_open;
9450 }
9451 }
9452
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009453 in->channel_mask = config->channel_mask;
9454 in->format = config->format;
9455
9456 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309457
9458 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9459 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9460 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9461 else {
9462 ret = -EINVAL;
9463 goto err_open;
9464 }
9465 }
9466
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009467 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309468 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9469 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009470 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9471 is_low_latency = true;
9472#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309473 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9474 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9475 else
9476 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009477#endif
9478 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009479 if (!in->realtime) {
9480 in->config = pcm_config_audio_capture;
9481 frame_size = audio_stream_in_frame_size(&in->stream);
9482 buffer_size = get_input_buffer_size(config->sample_rate,
9483 config->format,
9484 channel_count,
9485 is_low_latency);
9486 in->config.period_size = buffer_size / frame_size;
9487 in->config.rate = config->sample_rate;
9488 in->af_period_multiplier = 1;
9489 } else {
9490 // period size is left untouched for rt mode playback
9491 in->config = pcm_config_audio_capture_rt;
9492 in->af_period_multiplier = af_period_multiplier;
9493 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009494 }
9495
9496 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9497 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9498 in->realtime = 0;
9499 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9500 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009501 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009502 in->stream.start = in_start;
9503 in->stream.stop = in_stop;
9504 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9505 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009506 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009507 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009508 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9509 in->config = pcm_config_audio_capture;
9510 frame_size = audio_stream_in_frame_size(&in->stream);
9511 buffer_size = get_input_buffer_size(config->sample_rate,
9512 config->format,
9513 channel_count,
9514 false /*is_low_latency*/);
9515 in->config.period_size = buffer_size / frame_size;
9516 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009517 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009518 switch (config->format) {
9519 case AUDIO_FORMAT_PCM_32_BIT:
9520 in->bit_width = 32;
9521 break;
9522 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9523 case AUDIO_FORMAT_PCM_8_24_BIT:
9524 in->bit_width = 24;
9525 break;
9526 default:
9527 in->bit_width = 16;
9528 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009529 } else if (is_single_device_type_equal(&in->device_list,
9530 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9531 is_single_device_type_equal(&in->device_list,
9532 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009533 if (config->sample_rate == 0)
9534 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9535 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9536 config->sample_rate != 8000) {
9537 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9538 ret = -EINVAL;
9539 goto err_open;
9540 }
9541 if (config->format == AUDIO_FORMAT_DEFAULT)
9542 config->format = AUDIO_FORMAT_PCM_16_BIT;
9543 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9544 config->format = AUDIO_FORMAT_PCM_16_BIT;
9545 ret = -EINVAL;
9546 goto err_open;
9547 }
9548
9549 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009550 if (adev->ha_proxy_enable &&
9551 is_single_device_type_equal(&in->device_list,
9552 AUDIO_DEVICE_IN_TELEPHONY_RX))
9553 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009554 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009555 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009556 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309557 } else if (in->realtime) {
9558 in->config = pcm_config_audio_capture_rt;
9559 in->config.format = pcm_format_from_audio_format(config->format);
9560 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009561 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9562 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9563 (config->sample_rate == 8000 ||
9564 config->sample_rate == 16000 ||
9565 config->sample_rate == 32000 ||
9566 config->sample_rate == 48000) &&
9567 channel_count == 1) {
9568 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9569 in->config = pcm_config_audio_capture;
9570 frame_size = audio_stream_in_frame_size(&in->stream);
9571 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9572 config->sample_rate,
9573 config->format,
9574 channel_count, false /*is_low_latency*/);
9575 in->config.period_size = buffer_size / frame_size;
9576 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9577 in->config.rate = config->sample_rate;
9578 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009579 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309580 int ret_val;
9581 pthread_mutex_lock(&adev->lock);
9582 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9583 in, config, &channel_mask_updated);
9584 pthread_mutex_unlock(&adev->lock);
9585
9586 if (!ret_val) {
9587 if (channel_mask_updated == true) {
9588 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9589 __func__, config->channel_mask);
9590 ret = -EINVAL;
9591 goto err_open;
9592 }
9593 ALOGD("%s: created multi-channel session succesfully",__func__);
9594 } else if (audio_extn_compr_cap_enabled() &&
9595 audio_extn_compr_cap_format_supported(config->format) &&
9596 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9597 audio_extn_compr_cap_init(in);
9598 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309599 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309600 if (ret)
9601 goto err_open;
9602 } else {
9603 in->config = pcm_config_audio_capture;
9604 in->config.rate = config->sample_rate;
9605 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309606 in->format = config->format;
9607 frame_size = audio_stream_in_frame_size(&in->stream);
9608 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009609 config->format,
9610 channel_count,
9611 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009612 /* prevent division-by-zero */
9613 if (frame_size == 0) {
9614 ALOGE("%s: Error frame_size==0", __func__);
9615 ret = -EINVAL;
9616 goto err_open;
9617 }
9618
Revathi Uddarajud2634032017-12-07 14:42:34 +05309619 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009620 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009621
Revathi Uddarajud2634032017-12-07 14:42:34 +05309622 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9623 /* optionally use VOIP usecase depending on config(s) */
9624 ret = adev_update_voice_comm_input_stream(in, config);
9625 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009626
Revathi Uddarajud2634032017-12-07 14:42:34 +05309627 if (ret) {
9628 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9629 goto err_open;
9630 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009631 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309632
9633 /* assign concurrent capture usecase if record has to caried out from
9634 * actual hardware input source */
9635 if (audio_extn_is_concurrent_capture_enabled() &&
9636 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309637 /* Acquire lock to avoid two concurrent use cases initialized to
9638 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009639
Samyak Jainc37062f2019-04-25 18:41:06 +05309640 if (in->usecase == USECASE_AUDIO_RECORD) {
9641 pthread_mutex_lock(&adev->lock);
9642 if (!(adev->pcm_record_uc_state)) {
9643 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9644 adev->pcm_record_uc_state = 1;
9645 pthread_mutex_unlock(&adev->lock);
9646 } else {
9647 pthread_mutex_unlock(&adev->lock);
9648 /* Assign compress record use case for second record */
9649 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9650 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9651 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9652 if (audio_extn_cin_applicable_stream(in)) {
9653 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309654 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309655 if (ret)
9656 goto err_open;
9657 }
9658 }
9659 }
kunleiz28c73e72019-03-27 17:24:04 +08009660 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009661 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309662 if (audio_extn_ssr_get_stream() != in)
9663 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009664
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009665 in->sample_rate = in->config.rate;
9666
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309667 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9668 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009669 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009670 in->sample_rate, in->bit_width,
9671 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309672 register_format(in->format, in->supported_formats);
9673 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9674 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309675
Aalique Grahame22e49102018-12-18 14:23:57 -08009676 in->error_log = error_log_create(
9677 ERROR_LOG_ENTRIES,
9678 1000000000 /* aggregate consecutive identical errors within one second */);
9679
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009680 /* This stream could be for sound trigger lab,
9681 get sound trigger pcm if present */
9682 audio_extn_sound_trigger_check_and_get_session(in);
9683
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309684 lock_input_stream(in);
9685 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9686 pthread_mutex_lock(&adev->lock);
9687 in->card_status = adev->card_status;
9688 pthread_mutex_unlock(&adev->lock);
9689 pthread_mutex_unlock(&in->lock);
9690
Aalique Grahame22e49102018-12-18 14:23:57 -08009691 stream_app_type_cfg_init(&in->app_type_cfg);
9692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009693 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009695 ret = io_streams_map_insert(adev, &in->stream.common,
9696 handle, AUDIO_PATCH_HANDLE_NONE);
9697 if (ret != 0)
9698 goto err_open;
9699
Derek Chenf939fb72018-11-13 13:34:41 -08009700 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9701 calloc(1, sizeof(streams_input_ctxt_t));
9702 if (in_ctxt == NULL) {
9703 ALOGE("%s fail to allocate input ctxt", __func__);
9704 ret = -ENOMEM;
9705 goto err_open;
9706 }
9707 in_ctxt->input = in;
9708
9709 pthread_mutex_lock(&adev->lock);
9710 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9711 pthread_mutex_unlock(&adev->lock);
9712
Eric Laurent994a6932013-07-17 11:51:42 -07009713 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009714 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009715
9716err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309717 if (in->usecase == USECASE_AUDIO_RECORD) {
9718 pthread_mutex_lock(&adev->lock);
9719 adev->pcm_record_uc_state = 0;
9720 pthread_mutex_unlock(&adev->lock);
9721 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009722 free(in);
9723 *stream_in = NULL;
9724 return ret;
9725}
9726
9727static void adev_close_input_stream(struct audio_hw_device *dev,
9728 struct audio_stream_in *stream)
9729{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009730 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009731 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009732 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309733
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309734 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009735
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009736 if (in == NULL) {
9737 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9738 return;
9739 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009740 io_streams_map_remove(adev, in->capture_handle);
9741
kunleiz70e57612018-12-28 17:50:23 +08009742 /* must deregister from sndmonitor first to prevent races
9743 * between the callback and close_stream
9744 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309745 audio_extn_snd_mon_unregister_listener(stream);
9746
kunleiz70e57612018-12-28 17:50:23 +08009747 /* Disable echo reference if there are no active input, hfp call
9748 * and sound trigger while closing input stream
9749 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009750 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009751 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009752 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9753 struct listnode out_devices;
9754 list_init(&out_devices);
9755 platform_set_echo_reference(adev, false, &out_devices);
9756 } else
kunleiz70e57612018-12-28 17:50:23 +08009757 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309758
Weiyin Jiang2995f662019-04-17 14:25:12 +08009759 error_log_destroy(in->error_log);
9760 in->error_log = NULL;
9761
Pallavid7c7a272018-01-16 11:22:55 +05309762
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009763 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309764 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009765 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309766 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009767 if (ret != 0)
9768 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9769 __func__, ret);
9770 } else
9771 in_standby(&stream->common);
9772
Weiyin Jiang280ea742020-09-08 20:28:22 +08009773 pthread_mutex_destroy(&in->lock);
9774 pthread_mutex_destroy(&in->pre_lock);
9775
Revathi Uddarajud2634032017-12-07 14:42:34 +05309776 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309777 if (in->usecase == USECASE_AUDIO_RECORD) {
9778 adev->pcm_record_uc_state = 0;
9779 }
9780
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009781 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9782 adev->enable_voicerx = false;
9783 }
9784
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009785 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009786 audio_extn_ssr_deinit();
9787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009788
Garmond Leunge2433c32017-09-28 21:51:22 -07009789 if (audio_extn_ffv_get_stream() == in) {
9790 audio_extn_ffv_stream_deinit();
9791 }
9792
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309793 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009794 audio_extn_compr_cap_format_supported(in->config.format))
9795 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309796
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309797 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309798 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009799
Mingming Yinfd7607b2016-01-22 12:48:44 -08009800 if (in->is_st_session) {
9801 ALOGV("%s: sound trigger pcm stop lab", __func__);
9802 audio_extn_sound_trigger_stop_lab(in);
9803 }
Derek Chenf939fb72018-11-13 13:34:41 -08009804 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9805 if (in_ctxt != NULL) {
9806 list_remove(&in_ctxt->list);
9807 free(in_ctxt);
9808 } else {
9809 ALOGW("%s, input stream already closed", __func__);
9810 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009811 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309812 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009813 return;
9814}
9815
Aalique Grahame22e49102018-12-18 14:23:57 -08009816/* verifies input and output devices and their capabilities.
9817 *
9818 * This verification is required when enabling extended bit-depth or
9819 * sampling rates, as not all qcom products support it.
9820 *
9821 * Suitable for calling only on initialization such as adev_open().
9822 * It fills the audio_device use_case_table[] array.
9823 *
9824 * Has a side-effect that it needs to configure audio routing / devices
9825 * in order to power up the devices and read the device parameters.
9826 * It does not acquire any hw device lock. Should restore the devices
9827 * back to "normal state" upon completion.
9828 */
9829static int adev_verify_devices(struct audio_device *adev)
9830{
9831 /* enumeration is a bit difficult because one really wants to pull
9832 * the use_case, device id, etc from the hidden pcm_device_table[].
9833 * In this case there are the following use cases and device ids.
9834 *
9835 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9836 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9837 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9838 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9839 * [USECASE_AUDIO_RECORD] = {0, 0},
9840 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9841 * [USECASE_VOICE_CALL] = {2, 2},
9842 *
9843 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9844 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9845 */
9846
9847 /* should be the usecases enabled in adev_open_input_stream() */
9848 static const int test_in_usecases[] = {
9849 USECASE_AUDIO_RECORD,
9850 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9851 };
9852 /* should be the usecases enabled in adev_open_output_stream()*/
9853 static const int test_out_usecases[] = {
9854 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9855 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9856 };
9857 static const usecase_type_t usecase_type_by_dir[] = {
9858 PCM_PLAYBACK,
9859 PCM_CAPTURE,
9860 };
9861 static const unsigned flags_by_dir[] = {
9862 PCM_OUT,
9863 PCM_IN,
9864 };
9865
9866 size_t i;
9867 unsigned dir;
9868 const unsigned card_id = adev->snd_card;
9869
9870 for (dir = 0; dir < 2; ++dir) {
9871 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9872 const unsigned flags_dir = flags_by_dir[dir];
9873 const size_t testsize =
9874 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9875 const int *testcases =
9876 dir ? test_in_usecases : test_out_usecases;
9877 const audio_devices_t audio_device =
9878 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9879
9880 for (i = 0; i < testsize; ++i) {
9881 const audio_usecase_t audio_usecase = testcases[i];
9882 int device_id;
9883 struct pcm_params **pparams;
9884 struct stream_out out;
9885 struct stream_in in;
9886 struct audio_usecase uc_info;
9887 int retval;
9888
9889 pparams = &adev->use_case_table[audio_usecase];
9890 pcm_params_free(*pparams); /* can accept null input */
9891 *pparams = NULL;
9892
9893 /* find the device ID for the use case (signed, for error) */
9894 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9895 if (device_id < 0)
9896 continue;
9897
9898 /* prepare structures for device probing */
9899 memset(&uc_info, 0, sizeof(uc_info));
9900 uc_info.id = audio_usecase;
9901 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009902 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009903 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009904 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009905 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009906 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009907 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9908 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009909 }
9910 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009911 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009912 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009913 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009914 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009915 uc_info.in_snd_device = SND_DEVICE_NONE;
9916 uc_info.out_snd_device = SND_DEVICE_NONE;
9917 list_add_tail(&adev->usecase_list, &uc_info.list);
9918
9919 /* select device - similar to start_(in/out)put_stream() */
9920 retval = select_devices(adev, audio_usecase);
9921 if (retval >= 0) {
9922 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9923#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009924 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009925 if (*pparams) {
9926 ALOGV("%s: (%s) card %d device %d", __func__,
9927 dir ? "input" : "output", card_id, device_id);
9928 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9929 } else {
9930 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9931 }
9932#endif
9933 }
9934
9935 /* deselect device - similar to stop_(in/out)put_stream() */
9936 /* 1. Get and set stream specific mixer controls */
9937 retval = disable_audio_route(adev, &uc_info);
9938 /* 2. Disable the rx device */
9939 retval = disable_snd_device(adev,
9940 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9941 list_remove(&uc_info.list);
9942 }
9943 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009944 return 0;
9945}
9946
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009947int update_patch(unsigned int num_sources,
9948 const struct audio_port_config *sources,
9949 unsigned int num_sinks,
9950 const struct audio_port_config *sinks,
9951 audio_patch_handle_t handle,
9952 struct audio_patch_info *p_info,
9953 patch_type_t patch_type, bool new_patch)
9954{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009955 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009956
9957 if (p_info == NULL) {
9958 ALOGE("%s: Invalid patch pointer", __func__);
9959 return -EINVAL;
9960 }
9961
9962 if (new_patch) {
9963 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9964 if (p_info->patch == NULL) {
9965 ALOGE("%s: Could not allocate patch", __func__);
9966 return -ENOMEM;
9967 }
9968 }
9969
9970 p_info->patch->id = handle;
9971 p_info->patch->num_sources = num_sources;
9972 p_info->patch->num_sinks = num_sinks;
9973
9974 for (int i = 0; i < num_sources; i++)
9975 p_info->patch->sources[i] = sources[i];
9976 for (int i = 0; i < num_sinks; i++)
9977 p_info->patch->sinks[i] = sinks[i];
9978
9979 p_info->patch_type = patch_type;
9980 return 0;
9981}
9982
9983audio_patch_handle_t generate_patch_handle()
9984{
9985 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9986 if (++patch_handle < 0)
9987 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9988 return patch_handle;
9989}
9990
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309991int adev_create_audio_patch(struct audio_hw_device *dev,
9992 unsigned int num_sources,
9993 const struct audio_port_config *sources,
9994 unsigned int num_sinks,
9995 const struct audio_port_config *sinks,
9996 audio_patch_handle_t *handle)
9997{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009998 int ret = 0;
9999 struct audio_device *adev = (struct audio_device *)dev;
10000 struct audio_patch_info *p_info = NULL;
10001 patch_type_t patch_type = PATCH_NONE;
10002 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10003 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10004 struct audio_stream_info *s_info = NULL;
10005 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010006 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010007 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10008 bool new_patch = false;
10009 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010010
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010011 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10012 num_sources, num_sinks, *handle);
10013
10014 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10015 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10016 ALOGE("%s: Invalid patch arguments", __func__);
10017 ret = -EINVAL;
10018 goto done;
10019 }
10020
10021 if (num_sources > 1) {
10022 ALOGE("%s: Multiple sources are not supported", __func__);
10023 ret = -EINVAL;
10024 goto done;
10025 }
10026
10027 if (sources == NULL || sinks == NULL) {
10028 ALOGE("%s: Invalid sources or sinks port config", __func__);
10029 ret = -EINVAL;
10030 goto done;
10031 }
10032
10033 ALOGV("%s: source role %d, source type %d", __func__,
10034 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010035 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010036
10037 // Populate source/sink information and fetch stream info
10038 switch (sources[0].type) {
10039 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10040 device_type = sources[0].ext.device.type;
10041 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010042 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010043 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10044 patch_type = PATCH_CAPTURE;
10045 io_handle = sinks[0].ext.mix.handle;
10046 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010047 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010048 __func__, device_type, io_handle);
10049 } else {
10050 // Device to device patch is not implemented.
10051 // This space will need changes if audio HAL
10052 // handles device to device patches in the future.
10053 patch_type = PATCH_DEVICE_LOOPBACK;
10054 }
10055 break;
10056 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10057 io_handle = sources[0].ext.mix.handle;
10058 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010059 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010061 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010062 }
10063 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010064 ALOGD("%s: Playback patch from mix handle %d to device %x",
10065 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010066 break;
10067 case AUDIO_PORT_TYPE_SESSION:
10068 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010069 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10070 ret = -EINVAL;
10071 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 }
10073
10074 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010076 // Generate patch info and update patch
10077 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010078 *handle = generate_patch_handle();
10079 p_info = (struct audio_patch_info *)
10080 calloc(1, sizeof(struct audio_patch_info));
10081 if (p_info == NULL) {
10082 ALOGE("%s: Failed to allocate memory", __func__);
10083 pthread_mutex_unlock(&adev->lock);
10084 ret = -ENOMEM;
10085 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010087 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010088 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010089 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010090 if (p_info == NULL) {
10091 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10092 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010093 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010094 ret = -EINVAL;
10095 goto done;
10096 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010098 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010099 *handle, p_info, patch_type, new_patch);
10100
10101 // Fetch stream info of associated mix for playback or capture patches
10102 if (p_info->patch_type == PATCH_PLAYBACK ||
10103 p_info->patch_type == PATCH_CAPTURE) {
10104 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10105 if (s_info == NULL) {
10106 ALOGE("%s: Failed to obtain stream info", __func__);
10107 if (new_patch)
10108 free(p_info);
10109 pthread_mutex_unlock(&adev->lock);
10110 ret = -EINVAL;
10111 goto done;
10112 }
10113 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10114 s_info->patch_handle = *handle;
10115 stream = s_info->stream;
10116 }
10117 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010118
10119 // Update routing for stream
10120 if (stream != NULL) {
10121 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010122 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010123 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010124 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010125 if (ret < 0) {
10126 pthread_mutex_lock(&adev->lock);
10127 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10128 if (new_patch)
10129 free(p_info);
10130 pthread_mutex_unlock(&adev->lock);
10131 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10132 goto done;
10133 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010134 }
10135
10136 // Add new patch to patch map
10137 if (!ret && new_patch) {
10138 pthread_mutex_lock(&adev->lock);
10139 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010141 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010142 }
10143
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144done:
10145 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010146 num_sources,
10147 sources,
10148 num_sinks,
10149 sinks,
10150 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010151 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010152 num_sources,
10153 sources,
10154 num_sinks,
10155 sinks,
10156 handle);
10157 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010158}
10159
10160int adev_release_audio_patch(struct audio_hw_device *dev,
10161 audio_patch_handle_t handle)
10162{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010163 struct audio_device *adev = (struct audio_device *) dev;
10164 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010166 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010167
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010168 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10169 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10170 ret = -EINVAL;
10171 goto done;
10172 }
10173
10174 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010175 pthread_mutex_lock(&adev->lock);
10176 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010177 if (p_info == NULL) {
10178 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010179 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010180 ret = -EINVAL;
10181 goto done;
10182 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010183 struct audio_patch *patch = p_info->patch;
10184 if (patch == NULL) {
10185 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010186 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010188 goto done;
10189 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010190 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10191 switch (patch->sources[0].type) {
10192 case AUDIO_PORT_TYPE_MIX:
10193 io_handle = patch->sources[0].ext.mix.handle;
10194 break;
10195 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010196 if (p_info->patch_type == PATCH_CAPTURE)
10197 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010198 break;
10199 case AUDIO_PORT_TYPE_SESSION:
10200 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010201 pthread_mutex_unlock(&adev->lock);
10202 ret = -EINVAL;
10203 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010204 }
10205
10206 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010207 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010208 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010209 if (patch_type == PATCH_PLAYBACK ||
10210 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010211 struct audio_stream_info *s_info =
10212 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10213 if (s_info == NULL) {
10214 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10215 pthread_mutex_unlock(&adev->lock);
10216 goto done;
10217 }
10218 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10219 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010220 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010221 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010222
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010223 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010224 struct listnode devices;
10225 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010226 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010227 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010228 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010229 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010230 }
10231
10232 if (ret < 0)
10233 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10234
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010235done:
10236 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10237 audio_extn_auto_hal_release_audio_patch(dev, handle);
10238
10239 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010240 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010241}
10242
10243int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10244{
Derek Chenf13dd492018-11-13 14:53:51 -080010245 int ret = 0;
10246
10247 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10248 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10249 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010250}
10251
10252int adev_set_audio_port_config(struct audio_hw_device *dev,
10253 const struct audio_port_config *config)
10254{
Derek Chenf13dd492018-11-13 14:53:51 -080010255 int ret = 0;
10256
10257 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10258 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10259 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010260}
10261
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010262static int adev_dump(const audio_hw_device_t *device __unused,
10263 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010264{
10265 return 0;
10266}
10267
10268static int adev_close(hw_device_t *device)
10269{
Aalique Grahame22e49102018-12-18 14:23:57 -080010270 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010271 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010272
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010273 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010274 return 0;
10275
10276 pthread_mutex_lock(&adev_init_lock);
10277
10278 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010279 if (audio_extn_spkr_prot_is_enabled())
10280 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010281 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010282 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010283 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010284 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010285 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010286 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010287 audio_extn_utils_release_streams_cfg_lists(
10288 &adev->streams_output_cfg_list,
10289 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010290 if (audio_extn_qap_is_enabled())
10291 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010292 if (audio_extn_qaf_is_enabled())
10293 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010294 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010295 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010296 free(adev->snd_dev_ref_cnt);
10297 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010298 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10299 pcm_params_free(adev->use_case_table[i]);
10300 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010301 if (adev->adm_deinit)
10302 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010303 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010304 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010305 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010306 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010307 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010308 if (adev->device_cfg_params) {
10309 free(adev->device_cfg_params);
10310 adev->device_cfg_params = NULL;
10311 }
Derek Chend2530072014-11-24 12:39:14 -080010312 if(adev->ext_hw_plugin)
10313 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010314 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010315 free_map(adev->patch_map);
10316 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010317 free(device);
10318 adev = NULL;
10319 }
10320 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010321 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010322 return 0;
10323}
10324
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010325/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10326 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10327 * just that it _might_ work.
10328 */
10329static int period_size_is_plausible_for_low_latency(int period_size)
10330{
10331 switch (period_size) {
10332 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010333 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010334 case 240:
10335 case 320:
10336 case 480:
10337 return 1;
10338 default:
10339 return 0;
10340 }
10341}
10342
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010343static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10344{
10345 bool is_snd_card_status = false;
10346 bool is_ext_device_status = false;
10347 char value[32];
10348 int card = -1;
10349 card_status_t status;
10350
10351 if (cookie != adev || !parms)
10352 return;
10353
10354 if (!parse_snd_card_status(parms, &card, &status)) {
10355 is_snd_card_status = true;
10356 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10357 is_ext_device_status = true;
10358 } else {
10359 // not a valid event
10360 return;
10361 }
10362
10363 pthread_mutex_lock(&adev->lock);
10364 if (card == adev->snd_card || is_ext_device_status) {
10365 if (is_snd_card_status && adev->card_status != status) {
10366 adev->card_status = status;
10367 platform_snd_card_update(adev->platform, status);
10368 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010369 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010370 if (status == CARD_STATUS_OFFLINE)
10371 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010372 } else if (is_ext_device_status) {
10373 platform_set_parameters(adev->platform, parms);
10374 }
10375 }
10376 pthread_mutex_unlock(&adev->lock);
10377 return;
10378}
10379
Weiyin Jiang280ea742020-09-08 20:28:22 +080010380/* adev lock held */
10381int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010382{
10383 struct audio_usecase *uc_info;
10384 float left_p;
10385 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010386 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010387
10388 uc_info = get_usecase_from_list(adev, out->usecase);
10389 if (uc_info == NULL) {
10390 ALOGE("%s: Could not find the usecase (%d) in the list",
10391 __func__, out->usecase);
10392 return -EINVAL;
10393 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010394 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010395
10396 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10397 out->usecase, use_case_table[out->usecase]);
10398
10399 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010400 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010401 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010402 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010403 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010404 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10405 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010406 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Weiyin Jiang280ea742020-09-08 20:28:22 +080010407 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
10408 if (out->a2dp_compress_mute) {
10409 out->a2dp_compress_mute = false;
10410 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10411 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010412 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010413 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010414 out->muted = false;
10415 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010416 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010417 pthread_mutex_lock(&out->latch_lock);
Zhou Songc576a452019-09-09 14:17:40 +080010418 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10419 // mute compress stream if suspended
Zhou Songc576a452019-09-09 14:17:40 +080010420 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010421 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010422 assign_devices(&devices, &out->device_list);
10423 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010424 left_p = out->volume_l;
10425 right_p = out->volume_r;
10426 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10427 compress_pause(out->compr);
10428 out_set_compr_volume(&out->stream, (float)0, (float)0);
10429 out->a2dp_compress_mute = true;
10430 select_devices(adev, out->usecase);
10431 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10432 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010433 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010434 out->volume_l = left_p;
10435 out->volume_r = right_p;
10436 }
Zhou Songc576a452019-09-09 14:17:40 +080010437 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010438 // mute for non offloaded streams
10439 if (audio_extn_a2dp_source_is_suspended()) {
10440 out->muted = true;
10441 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010442 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010443 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010444 }
10445 ALOGV("%s: exit", __func__);
10446 return 0;
10447}
10448
Haynes Mathew George01156f92018-04-13 15:29:54 -070010449void adev_on_battery_status_changed(bool charging)
10450{
10451 pthread_mutex_lock(&adev->lock);
10452 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10453 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010454 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010455 pthread_mutex_unlock(&adev->lock);
10456}
10457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010458static int adev_open(const hw_module_t *module, const char *name,
10459 hw_device_t **device)
10460{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010461 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010462 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010463 char mixer_ctl_name[128] = {0};
10464 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010465
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010466 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010467 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10468
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010469 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010470 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010471 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010472 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010473 ALOGD("%s: returning existing instance of adev", __func__);
10474 ALOGD("%s: exit", __func__);
10475 pthread_mutex_unlock(&adev_init_lock);
10476 return 0;
10477 }
10478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010479 adev = calloc(1, sizeof(struct audio_device));
10480
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010481 if (!adev) {
10482 pthread_mutex_unlock(&adev_init_lock);
10483 return -ENOMEM;
10484 }
10485
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010486 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10487
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010488 // register audio ext hidl at the earliest
10489 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010490#ifdef DYNAMIC_LOG_ENABLED
10491 register_for_dynamic_logging("hal");
10492#endif
10493
Derek Chenf939fb72018-11-13 13:34:41 -080010494 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010495 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010496 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10497 maj_version = atoi(value);
10498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010499 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010500 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010501 adev->device.common.module = (struct hw_module_t *)module;
10502 adev->device.common.close = adev_close;
10503
10504 adev->device.init_check = adev_init_check;
10505 adev->device.set_voice_volume = adev_set_voice_volume;
10506 adev->device.set_master_volume = adev_set_master_volume;
10507 adev->device.get_master_volume = adev_get_master_volume;
10508 adev->device.set_master_mute = adev_set_master_mute;
10509 adev->device.get_master_mute = adev_get_master_mute;
10510 adev->device.set_mode = adev_set_mode;
10511 adev->device.set_mic_mute = adev_set_mic_mute;
10512 adev->device.get_mic_mute = adev_get_mic_mute;
10513 adev->device.set_parameters = adev_set_parameters;
10514 adev->device.get_parameters = adev_get_parameters;
10515 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10516 adev->device.open_output_stream = adev_open_output_stream;
10517 adev->device.close_output_stream = adev_close_output_stream;
10518 adev->device.open_input_stream = adev_open_input_stream;
10519 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010520 adev->device.create_audio_patch = adev_create_audio_patch;
10521 adev->device.release_audio_patch = adev_release_audio_patch;
10522 adev->device.get_audio_port = adev_get_audio_port;
10523 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010524 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010525 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010526
10527 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010528 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010529 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010530 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010531 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010532 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010533 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010534 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010535 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010536 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010537 /* Init audio and voice feature */
10538 audio_extn_feature_init();
10539 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010540 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010541 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010542 list_init(&adev->active_inputs_list);
10543 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010544 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010545 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10546 audio_extn_utils_hash_eq);
10547 if (!adev->io_streams_map) {
10548 ALOGE("%s: Could not create io streams map", __func__);
10549 ret = -ENOMEM;
10550 goto adev_open_err;
10551 }
10552 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10553 audio_extn_utils_hash_eq);
10554 if (!adev->patch_map) {
10555 ALOGE("%s: Could not create audio patch map", __func__);
10556 ret = -ENOMEM;
10557 goto adev_open_err;
10558 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010559 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010560 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010561 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010562 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010563 adev->perf_lock_opts[0] = 0x101;
10564 adev->perf_lock_opts[1] = 0x20E;
10565 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010566 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010567 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010568 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010569 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010570 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010571
Zhou Song68ebc352019-12-05 17:11:15 +080010572 audio_extn_perf_lock_init();
10573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010574 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010575 adev->platform = platform_init(adev);
10576 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010577 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010578 ret = -EINVAL;
10579 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010580 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010581
Aalique Grahame22e49102018-12-18 14:23:57 -080010582 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010583 if (audio_extn_qap_is_enabled()) {
10584 ret = audio_extn_qap_init(adev);
10585 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010586 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010587 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010588 }
10589 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10590 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10591 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010592
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010593 if (audio_extn_qaf_is_enabled()) {
10594 ret = audio_extn_qaf_init(adev);
10595 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010596 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010597 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010598 }
10599
10600 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10601 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10602 }
10603
Derek Chenae7b0342019-02-08 15:17:04 -080010604 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010605 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10606
Eric Laurentc4aef752013-09-12 17:45:53 -070010607 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10608 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10609 if (adev->visualizer_lib == NULL) {
10610 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10611 } else {
10612 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10613 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010614 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010615 "visualizer_hal_start_output");
10616 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010617 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010618 "visualizer_hal_stop_output");
10619 }
10620 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010621 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010622 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010623 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010624 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010625 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010626 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010627
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010628 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10629 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10630 if (adev->offload_effects_lib == NULL) {
10631 ALOGE("%s: DLOPEN failed for %s", __func__,
10632 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10633 } else {
10634 ALOGV("%s: DLOPEN successful for %s", __func__,
10635 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10636 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010637 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010638 "offload_effects_bundle_hal_start_output");
10639 adev->offload_effects_stop_output =
10640 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10641 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010642 adev->offload_effects_set_hpx_state =
10643 (int (*)(bool))dlsym(adev->offload_effects_lib,
10644 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010645 adev->offload_effects_get_parameters =
10646 (void (*)(struct str_parms *, struct str_parms *))
10647 dlsym(adev->offload_effects_lib,
10648 "offload_effects_bundle_get_parameters");
10649 adev->offload_effects_set_parameters =
10650 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10651 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010652 }
10653 }
10654
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010655 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10656 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10657 if (adev->adm_lib == NULL) {
10658 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10659 } else {
10660 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10661 adev->adm_init = (adm_init_t)
10662 dlsym(adev->adm_lib, "adm_init");
10663 adev->adm_deinit = (adm_deinit_t)
10664 dlsym(adev->adm_lib, "adm_deinit");
10665 adev->adm_register_input_stream = (adm_register_input_stream_t)
10666 dlsym(adev->adm_lib, "adm_register_input_stream");
10667 adev->adm_register_output_stream = (adm_register_output_stream_t)
10668 dlsym(adev->adm_lib, "adm_register_output_stream");
10669 adev->adm_deregister_stream = (adm_deregister_stream_t)
10670 dlsym(adev->adm_lib, "adm_deregister_stream");
10671 adev->adm_request_focus = (adm_request_focus_t)
10672 dlsym(adev->adm_lib, "adm_request_focus");
10673 adev->adm_abandon_focus = (adm_abandon_focus_t)
10674 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010675 adev->adm_set_config = (adm_set_config_t)
10676 dlsym(adev->adm_lib, "adm_set_config");
10677 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10678 dlsym(adev->adm_lib, "adm_request_focus_v2");
10679 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10680 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10681 adev->adm_on_routing_change = (adm_on_routing_change_t)
10682 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010683 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10684 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010685 }
10686 }
10687
Aalique Grahame22e49102018-12-18 14:23:57 -080010688 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010689 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010690 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010691 //initialize this to false for now,
10692 //this will be set to true through set param
10693 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010694
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010695 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010696 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010697
10698 if (k_enable_extended_precision)
10699 adev_verify_devices(adev);
10700
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010701 adev->dsp_bit_width_enforce_mode =
10702 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010703
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010704 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10705 &adev->streams_output_cfg_list,
10706 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010707
Kiran Kandi910e1862013-10-29 13:29:42 -070010708 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010709
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010710 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010711 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010712 trial = atoi(value);
10713 if (period_size_is_plausible_for_low_latency(trial)) {
10714 pcm_config_low_latency.period_size = trial;
10715 pcm_config_low_latency.start_threshold = trial / 4;
10716 pcm_config_low_latency.avail_min = trial / 4;
10717 configured_low_latency_capture_period_size = trial;
10718 }
10719 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010720 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10721 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010722 trial = atoi(value);
10723 if (period_size_is_plausible_for_low_latency(trial)) {
10724 configured_low_latency_capture_period_size = trial;
10725 }
10726 }
10727
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010728 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10729
Eric Laurent4b084132018-10-19 17:33:43 -070010730 adev->camera_orientation = CAMERA_DEFAULT;
10731
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010732 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010733 af_period_multiplier = atoi(value);
10734 if (af_period_multiplier < 0)
10735 af_period_multiplier = 2;
10736 else if (af_period_multiplier > 4)
10737 af_period_multiplier = 4;
10738
10739 ALOGV("new period_multiplier = %d", af_period_multiplier);
10740 }
10741
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010742 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010743
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010744 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010745 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010746 pthread_mutex_unlock(&adev_init_lock);
10747
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010748 if (adev->adm_init)
10749 adev->adm_data = adev->adm_init();
10750
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010751 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010752 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010753
10754 audio_extn_snd_mon_init();
10755 pthread_mutex_lock(&adev->lock);
10756 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10757 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010758 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10759 /*
10760 * if the battery state callback happens before charging can be queried,
10761 * it will be guarded with the adev->lock held in the cb function and so
10762 * the callback value will reflect the latest state
10763 */
10764 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010765 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010766 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010767 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010768 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010769 /* Allocate memory for Device config params */
10770 adev->device_cfg_params = (struct audio_device_config_param*)
10771 calloc(platform_get_max_codec_backend(),
10772 sizeof(struct audio_device_config_param));
10773 if (adev->device_cfg_params == NULL)
10774 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010775
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010776 /*
10777 * Check if new PSPD matrix mixer control is supported. If not
10778 * supported, then set flag so that old mixer ctrl is sent while
10779 * sending pspd coefficients on older kernel version. Query mixer
10780 * control for default pcm id and channel value one.
10781 */
10782 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10783 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10784
10785 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10786 if (!ctl) {
10787 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10788 __func__, mixer_ctl_name);
10789 adev->use_old_pspd_mix_ctrl = true;
10790 }
10791
Eric Laurent994a6932013-07-17 11:51:42 -070010792 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010793 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010794
10795adev_open_err:
10796 free_map(adev->patch_map);
10797 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010798 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010799 pthread_mutex_destroy(&adev->lock);
10800 free(adev);
10801 adev = NULL;
10802 *device = NULL;
10803 pthread_mutex_unlock(&adev_init_lock);
10804 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010805}
10806
10807static struct hw_module_methods_t hal_module_methods = {
10808 .open = adev_open,
10809};
10810
10811struct audio_module HAL_MODULE_INFO_SYM = {
10812 .common = {
10813 .tag = HARDWARE_MODULE_TAG,
10814 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10815 .hal_api_version = HARDWARE_HAL_API_VERSION,
10816 .id = AUDIO_HARDWARE_MODULE_ID,
10817 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010818 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010819 .methods = &hal_module_methods,
10820 },
10821};