blob: a88fd5ad7df67e5a490b3fe0c7012ace5b1fbc35 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Zhou Song642ec432020-12-23 16:11:10 +08002 * Copyright (c) 2013-2021, 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
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700151static unsigned int configured_low_latency_capture_period_size =
152 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
153
Haynes Mathew George16081042017-05-31 17:16:49 -0700154#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
155#define MMAP_PERIOD_COUNT_MIN 32
156#define MMAP_PERIOD_COUNT_MAX 512
157#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
158
Aalique Grahame22e49102018-12-18 14:23:57 -0800159/* This constant enables extended precision handling.
160 * TODO The flag is off until more testing is done.
161 */
162static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700163extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800164
Eric Laurentb23d5282013-05-14 15:27:20 -0700165struct pcm_config pcm_config_deep_buffer = {
166 .channels = 2,
167 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
168 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
169 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
172 .stop_threshold = INT_MAX,
173 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
174};
175
176struct pcm_config pcm_config_low_latency = {
177 .channels = 2,
178 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
179 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
180 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
183 .stop_threshold = INT_MAX,
184 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185};
186
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800187struct pcm_config pcm_config_haptics_audio = {
188 .channels = 1,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
191 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
194 .stop_threshold = INT_MAX,
195 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
196};
197
198struct pcm_config pcm_config_haptics = {
199 .channels = 1,
200 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
201 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
202 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
203 .format = PCM_FORMAT_S16_LE,
204 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .stop_threshold = INT_MAX,
206 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209static int af_period_multiplier = 4;
210struct pcm_config pcm_config_rt = {
211 .channels = 2,
212 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
213 .period_size = ULL_PERIOD_SIZE, //1 ms
214 .period_count = 512, //=> buffer size is 512ms
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
217 .stop_threshold = INT_MAX,
218 .silence_threshold = 0,
219 .silence_size = 0,
220 .avail_min = ULL_PERIOD_SIZE, //1 ms
221};
222
Eric Laurentb23d5282013-05-14 15:27:20 -0700223struct pcm_config pcm_config_hdmi_multi = {
224 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
225 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
226 .period_size = HDMI_MULTI_PERIOD_SIZE,
227 .period_count = HDMI_MULTI_PERIOD_COUNT,
228 .format = PCM_FORMAT_S16_LE,
229 .start_threshold = 0,
230 .stop_threshold = INT_MAX,
231 .avail_min = 0,
232};
233
Haynes Mathew George16081042017-05-31 17:16:49 -0700234struct pcm_config pcm_config_mmap_playback = {
235 .channels = 2,
236 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
237 .period_size = MMAP_PERIOD_SIZE,
238 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
239 .format = PCM_FORMAT_S16_LE,
240 .start_threshold = MMAP_PERIOD_SIZE*8,
241 .stop_threshold = INT32_MAX,
242 .silence_threshold = 0,
243 .silence_size = 0,
244 .avail_min = MMAP_PERIOD_SIZE, //1 ms
245};
246
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700247struct pcm_config pcm_config_hifi = {
248 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
249 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
250 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
251 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
252 .format = PCM_FORMAT_S24_3LE,
253 .start_threshold = 0,
254 .stop_threshold = INT_MAX,
255 .avail_min = 0,
256};
257
Eric Laurentb23d5282013-05-14 15:27:20 -0700258struct pcm_config pcm_config_audio_capture = {
259 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
261 .format = PCM_FORMAT_S16_LE,
262};
263
Haynes Mathew George16081042017-05-31 17:16:49 -0700264struct pcm_config pcm_config_mmap_capture = {
265 .channels = 2,
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
267 .period_size = MMAP_PERIOD_SIZE,
268 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
269 .format = PCM_FORMAT_S16_LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .silence_threshold = 0,
273 .silence_size = 0,
274 .avail_min = MMAP_PERIOD_SIZE, //1 ms
275};
276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700277#define AFE_PROXY_CHANNEL_COUNT 2
278#define AFE_PROXY_SAMPLING_RATE 48000
279
280#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
281#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
282
283struct pcm_config pcm_config_afe_proxy_playback = {
284 .channels = AFE_PROXY_CHANNEL_COUNT,
285 .rate = AFE_PROXY_SAMPLING_RATE,
286 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
287 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
288 .format = PCM_FORMAT_S16_LE,
289 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
290 .stop_threshold = INT_MAX,
291 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
292};
293
294#define AFE_PROXY_RECORD_PERIOD_SIZE 768
295#define AFE_PROXY_RECORD_PERIOD_COUNT 4
296
Aalique Grahame22e49102018-12-18 14:23:57 -0800297struct pcm_config pcm_config_audio_capture_rt = {
298 .channels = 2,
299 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
300 .period_size = ULL_PERIOD_SIZE,
301 .period_count = 512,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = 0,
304 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
305 .silence_threshold = 0,
306 .silence_size = 0,
307 .avail_min = ULL_PERIOD_SIZE, //1 ms
308};
309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700310struct pcm_config pcm_config_afe_proxy_record = {
311 .channels = AFE_PROXY_CHANNEL_COUNT,
312 .rate = AFE_PROXY_SAMPLING_RATE,
313 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
314 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
315 .format = PCM_FORMAT_S16_LE,
316 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
317 .stop_threshold = INT_MAX,
318 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
319};
320
Ashish Jainf1eaa582016-05-23 20:54:24 +0530321#define AUDIO_MAX_PCM_FORMATS 7
322
323const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
324 [AUDIO_FORMAT_DEFAULT] = 0,
325 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
326 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
327 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
329 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
330 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
331};
332
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800333const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700334 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
335 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800336 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800337 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700338 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
339 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700340 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700341 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
349 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700350 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
351 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700352 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800353 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700354
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700356 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530357 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
358 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
359 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530360 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
361 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700363 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700364 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700365 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700366
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800367 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800368 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400369 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
370 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700371
Derek Chenf7092792017-05-23 12:23:53 -0400372 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700373 [USECASE_VOICE2_CALL] = "voice2-call",
374 [USECASE_VOLTE_CALL] = "volte-call",
375 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800376 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800377 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
378 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800379 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700380 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
381 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
382 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800383 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
384 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
385 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
386
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700387 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
388 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700389 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
390 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700391
392 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
393 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800394 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530395 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700396
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530397 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
399 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700400
401 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
402 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530403 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530404 /* For Interactive Audio Streams */
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
412 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700413
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800414 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
415
Derek Chenf6318be2017-06-12 17:16:24 -0400416 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
417
418 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
419 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
420 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
421 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800422 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700423 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530424 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500425 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400426
427 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
428 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
429 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800430 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500431 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700432};
433
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700434static const audio_usecase_t offload_usecases[] = {
435 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
441 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
442 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
443 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700444};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445
Varun Balaraje49253e2017-07-06 19:48:56 +0530446static const audio_usecase_t interactive_usecases[] = {
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
452 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
453 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
454 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
455};
456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457#define STRING_TO_ENUM(string) { #string, string }
458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800459struct string_to_enum {
460 const char *name;
461 uint32_t value;
462};
463
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800470 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
471 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800472 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700473 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
474 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
475 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
481 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
482 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
483 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum formats_name_to_enum_table[] = {
487 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
488 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
489 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700490 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
491 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
492 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700493 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800494 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
495 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700496 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800497};
498
499//list of all supported sample rates by HDMI specification.
500static const int out_hdmi_sample_rates[] = {
501 32000, 44100, 48000, 88200, 96000, 176400, 192000,
502};
503
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700504static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800505 STRING_TO_ENUM(32000),
506 STRING_TO_ENUM(44100),
507 STRING_TO_ENUM(48000),
508 STRING_TO_ENUM(88200),
509 STRING_TO_ENUM(96000),
510 STRING_TO_ENUM(176400),
511 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800512 STRING_TO_ENUM(352800),
513 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700514};
515
Carter Hsu2e429db2019-05-14 18:50:52 +0800516struct in_effect_list {
517 struct listnode list;
518 effect_handle_t handle;
519};
520
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700521static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700522static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700523static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700524//cache last MBDRC cal step level
525static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700526
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530527static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700528static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800529static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530530static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530531
Derek Chen6f293672019-04-01 01:40:24 -0700532static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
533static void in_snd_mon_cb(void * stream, struct str_parms * parms);
534static void out_snd_mon_cb(void * stream, struct str_parms * parms);
535
Zhou Song331c8e52019-08-26 14:16:12 +0800536static int configure_btsco_sample_rate(snd_device_t snd_device);
537
Vatsal Buchac09ae062018-11-14 13:25:08 +0530538#ifdef AUDIO_FEATURE_ENABLED_GCOV
539extern void __gcov_flush();
540static void enable_gcov()
541{
542 __gcov_flush();
543}
544#else
545static void enable_gcov()
546{
547}
548#endif
549
justinweng20fb6d82019-02-21 18:49:00 -0700550static int in_set_microphone_direction(const struct audio_stream_in *stream,
551 audio_microphone_direction_t dir);
552static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
553
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700554static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
555 int flags __unused)
556{
557 int dir = 0;
558 switch (uc_id) {
559 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530560 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700561 dir = 1;
562 case USECASE_AUDIO_PLAYBACK_ULL:
563 break;
564 default:
565 return false;
566 }
567
568 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
569 PCM_PLAYBACK : PCM_CAPTURE);
570 if (adev->adm_is_noirq_avail)
571 return adev->adm_is_noirq_avail(adev->adm_data,
572 adev->snd_card, dev_id, dir);
573 return false;
574}
575
576static void register_out_stream(struct stream_out *out)
577{
578 struct audio_device *adev = out->dev;
579 if (is_offload_usecase(out->usecase) ||
580 !adev->adm_register_output_stream)
581 return;
582
583 // register stream first for backward compatibility
584 adev->adm_register_output_stream(adev->adm_data,
585 out->handle,
586 out->flags);
587
588 if (!adev->adm_set_config)
589 return;
590
591 if (out->realtime)
592 adev->adm_set_config(adev->adm_data,
593 out->handle,
594 out->pcm, &out->config);
595}
596
597static void register_in_stream(struct stream_in *in)
598{
599 struct audio_device *adev = in->dev;
600 if (!adev->adm_register_input_stream)
601 return;
602
603 adev->adm_register_input_stream(adev->adm_data,
604 in->capture_handle,
605 in->flags);
606
607 if (!adev->adm_set_config)
608 return;
609
610 if (in->realtime)
611 adev->adm_set_config(adev->adm_data,
612 in->capture_handle,
613 in->pcm,
614 &in->config);
615}
616
617static void request_out_focus(struct stream_out *out, long ns)
618{
619 struct audio_device *adev = out->dev;
620
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 if (adev->adm_request_focus_v2)
622 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
623 else if (adev->adm_request_focus)
624 adev->adm_request_focus(adev->adm_data, out->handle);
625}
626
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700627static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628{
629 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700630 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700632 if (adev->adm_request_focus_v2_1)
633 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
634 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700635 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
636 else if (adev->adm_request_focus)
637 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700638
639 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700640}
641
642static void release_out_focus(struct stream_out *out)
643{
644 struct audio_device *adev = out->dev;
645
646 if (adev->adm_abandon_focus)
647 adev->adm_abandon_focus(adev->adm_data, out->handle);
648}
649
650static void release_in_focus(struct stream_in *in)
651{
652 struct audio_device *adev = in->dev;
653 if (adev->adm_abandon_focus)
654 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
655}
656
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530657static int parse_snd_card_status(struct str_parms *parms, int *card,
658 card_status_t *status)
659{
660 char value[32]={0};
661 char state[32]={0};
662
663 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
664 if (ret < 0)
665 return -1;
666
667 // sscanf should be okay as value is of max length 32.
668 // same as sizeof state.
669 if (sscanf(value, "%d,%s", card, state) < 2)
670 return -1;
671
672 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
673 CARD_STATUS_OFFLINE;
674 return 0;
675}
676
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700677static inline void adjust_frames_for_device_delay(struct stream_out *out,
678 uint32_t *dsp_frames) {
679 // Adjustment accounts for A2dp encoder latency with offload usecases
680 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800681 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700682 unsigned long offset =
683 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
684 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
685 }
686}
687
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700688static inline bool free_entry(void *key __unused,
689 void *value, void *context __unused)
690{
691 free(value);
692 return true;
693}
694
695static inline void free_map(Hashmap *map)
696{
697 if (map) {
698 hashmapForEach(map, free_entry, (void *) NULL);
699 hashmapFree(map);
700 }
701}
702
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800703static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700704 audio_patch_handle_t patch_handle)
705{
706 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
707 return;
708
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700709 struct audio_patch_info *p_info =
710 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
711 if (p_info) {
712 ALOGV("%s: Remove patch %d", __func__, patch_handle);
713 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
714 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715 free(p_info);
716 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700717}
718
719static inline int io_streams_map_insert(struct audio_device *adev,
720 struct audio_stream *stream,
721 audio_io_handle_t handle,
722 audio_patch_handle_t patch_handle)
723{
724 struct audio_stream_info *s_info =
725 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
726
727 if (s_info == NULL) {
728 ALOGE("%s: Could not allocate stream info", __func__);
729 return -ENOMEM;
730 }
731 s_info->stream = stream;
732 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700733
734 pthread_mutex_lock(&adev->lock);
735 struct audio_stream_info *stream_info =
736 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700737 if (stream_info != NULL)
738 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700740 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 return 0;
742}
743
744static inline void io_streams_map_remove(struct audio_device *adev,
745 audio_io_handle_t handle)
746{
747 pthread_mutex_lock(&adev->lock);
748 struct audio_stream_info *s_info =
749 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700752 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800755done:
756 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return;
758}
759
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800760static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700761 audio_patch_handle_t handle)
762{
763 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700764 p_info = (struct audio_patch_info *)
765 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700766 return p_info;
767}
768
vivek mehtaa76401a2015-04-24 14:12:15 -0700769__attribute__ ((visibility ("default")))
770bool audio_hw_send_gain_dep_calibration(int level) {
771 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700772 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700773
774 pthread_mutex_lock(&adev_init_lock);
775
776 if (adev != NULL && adev->platform != NULL) {
777 pthread_mutex_lock(&adev->lock);
778 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700779
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530780 // cache level info for any of the use case which
781 // was not started.
782 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700783
vivek mehtaa76401a2015-04-24 14:12:15 -0700784 pthread_mutex_unlock(&adev->lock);
785 } else {
786 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
787 }
788
789 pthread_mutex_unlock(&adev_init_lock);
790
791 return ret_val;
792}
793
Ashish Jain5106d362016-05-11 19:23:33 +0530794static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
795{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796 bool gapless_enabled = false;
797 const char *mixer_ctl_name = "Compress Gapless Playback";
798 struct mixer_ctl *ctl;
799
800 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700801 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530802
803 /*Disable gapless if its AV playback*/
804 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800805
806 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
807 if (!ctl) {
808 ALOGE("%s: Could not get ctl for mixer cmd - %s",
809 __func__, mixer_ctl_name);
810 return -EINVAL;
811 }
812
813 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
814 ALOGE("%s: Could not set gapless mode %d",
815 __func__, gapless_enabled);
816 return -EINVAL;
817 }
818 return 0;
819}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700820
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700821__attribute__ ((visibility ("default")))
822int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
823 int table_size) {
824 int ret_val = 0;
825 ALOGV("%s: enter ... ", __func__);
826
827 pthread_mutex_lock(&adev_init_lock);
828 if (adev == NULL) {
829 ALOGW("%s: adev is NULL .... ", __func__);
830 goto done;
831 }
832
833 pthread_mutex_lock(&adev->lock);
834 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
835 pthread_mutex_unlock(&adev->lock);
836done:
837 pthread_mutex_unlock(&adev_init_lock);
838 ALOGV("%s: exit ... ", __func__);
839 return ret_val;
840}
841
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800843{
844 bool ret = false;
845 ALOGV("%s: enter ...", __func__);
846
847 pthread_mutex_lock(&adev_init_lock);
848
849 if (adev != NULL && adev->platform != NULL) {
850 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800851 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800852 pthread_mutex_unlock(&adev->lock);
853 }
854
855 pthread_mutex_unlock(&adev_init_lock);
856
857 ALOGV("%s: exit with ret %d", __func__, ret);
858 return ret;
859}
Aalique Grahame22e49102018-12-18 14:23:57 -0800860
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700861static bool is_supported_format(audio_format_t format)
862{
Eric Laurent86e17132013-09-12 17:49:30 -0700863 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530864 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530865 format == AUDIO_FORMAT_AAC_LC ||
866 format == AUDIO_FORMAT_AAC_HE_V1 ||
867 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530868 format == AUDIO_FORMAT_AAC_ADTS_LC ||
869 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
870 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530871 format == AUDIO_FORMAT_AAC_LATM_LC ||
872 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
873 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530874 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
875 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530876 format == AUDIO_FORMAT_PCM_FLOAT ||
877 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700878 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530879 format == AUDIO_FORMAT_AC3 ||
880 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700881 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530882 format == AUDIO_FORMAT_DTS ||
883 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800884 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530885 format == AUDIO_FORMAT_ALAC ||
886 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530887 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530888 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800889 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530890 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700891 format == AUDIO_FORMAT_APTX ||
892 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800893 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700894
895 return false;
896}
897
Kunlei Zhang67cc7072020-12-18 17:16:49 +0800898static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
899{
900 struct listnode *node;
901 struct audio_usecase *usecase;
902
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
905 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
906 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
907 return false;
908 }
909 }
910
911 return true;
912}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700913static inline bool is_mmap_usecase(audio_usecase_t uc_id)
914{
915 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800916 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700917 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
918}
919
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700920static inline bool is_valid_volume(float left, float right)
921{
922 return ((left >= 0.0f && right >= 0.0f) ? true : false);
923}
924
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530925static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530926{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530927 ALOGV("%s", __func__);
928 audio_route_apply_and_update_path(adev->audio_route,
929 "asrc-mode");
930 adev->asrc_mode_enabled = true;
931}
932
933static void disable_asrc_mode(struct audio_device *adev)
934{
935 ALOGV("%s", __func__);
936 audio_route_reset_and_update_path(adev->audio_route,
937 "asrc-mode");
938 adev->asrc_mode_enabled = false;
939}
940
Saurav Kumarc1411662020-10-14 10:50:45 +0530941static void check_and_configure_headphone(struct audio_device *adev,
942 struct audio_usecase *uc_info,
943 snd_device_t snd_device)
944{
945 struct listnode *node;
946 struct audio_usecase *usecase;
947 int new_backend_idx, usecase_backend_idx;
948 bool spkr_hph_single_be_native_concurrency;
949
950 new_backend_idx = platform_get_backend_index(snd_device);
951 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +0800952 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
953 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +0530954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
957 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
958 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
959 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
960 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->out_snd_device);
963 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530964 platform_check_and_set_codec_backend_cfg(adev, usecase,
965 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530966 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +0800967 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +0530968 }
969 }
970 }
971 }
972}
973
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530974/*
975 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
976 * 44.1 or Native DSD backends are enabled for any of current use case.
977 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
978 * - Disable current mix path use case(Headphone backend) and re-enable it with
979 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
980 * e.g. Naitve DSD or Headphone 44.1 -> + 48
981 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530982static void check_and_set_asrc_mode(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530985{
986 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530987 int i, num_new_devices = 0;
988 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
989 /*
990 *Split snd device for new combo use case
991 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
992 */
993 if (platform_split_snd_device(adev->platform,
994 snd_device,
995 &num_new_devices,
996 split_new_snd_devices) == 0) {
997 for (i = 0; i < num_new_devices; i++)
998 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
999 } else {
1000 int new_backend_idx = platform_get_backend_index(snd_device);
1001 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1002 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1003 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1004 !adev->asrc_mode_enabled) {
1005 struct listnode *node = NULL;
1006 struct audio_usecase *uc = NULL;
1007 struct stream_out *curr_out = NULL;
1008 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1009 int i, num_devices, ret = 0;
1010 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301011
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301012 list_for_each(node, &adev->usecase_list) {
1013 uc = node_to_item(node, struct audio_usecase, list);
1014 curr_out = (struct stream_out*) uc->stream.out;
1015 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1016 /*
1017 *Split snd device for existing combo use case
1018 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1019 */
1020 ret = platform_split_snd_device(adev->platform,
1021 uc->out_snd_device,
1022 &num_devices,
1023 split_snd_devices);
1024 if (ret < 0 || num_devices == 0) {
1025 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1026 split_snd_devices[0] = uc->out_snd_device;
1027 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001028 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301029 for (i = 0; i < num_devices; i++) {
1030 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1031 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1032 if((new_backend_idx == HEADPHONE_BACKEND) &&
1033 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1034 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001035 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301036 __func__);
1037 enable_asrc_mode(adev);
1038 break;
1039 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1040 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1041 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001042 ALOGV("%s: 48K stream detected, disabling and enabling it \
1043 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301044 disable_audio_route(adev, uc);
1045 disable_snd_device(adev, uc->out_snd_device);
1046 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1047 if (new_backend_idx == DSD_NATIVE_BACKEND)
1048 audio_route_apply_and_update_path(adev->audio_route,
1049 "hph-true-highquality-mode");
1050 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1051 (curr_out->bit_width >= 24))
1052 audio_route_apply_and_update_path(adev->audio_route,
1053 "hph-highquality-mode");
1054 enable_asrc_mode(adev);
1055 enable_snd_device(adev, uc->out_snd_device);
1056 enable_audio_route(adev, uc);
1057 break;
1058 }
1059 }
1060 // reset split devices count
1061 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001062 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301063 if (adev->asrc_mode_enabled)
1064 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301065 }
1066 }
1067 }
1068}
1069
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001070static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1071 struct audio_effect_config effect_config,
1072 unsigned int param_value)
1073{
1074 char mixer_ctl_name[] = "Audio Effect";
1075 struct mixer_ctl *ctl;
1076 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001077 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001078
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001079 if (in == NULL) {
1080 ALOGE("%s: active input stream is NULL", __func__);
1081 return -EINVAL;
1082 }
1083
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001084 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1085 if (!ctl) {
1086 ALOGE("%s: Could not get mixer ctl - %s",
1087 __func__, mixer_ctl_name);
1088 return -EINVAL;
1089 }
1090
1091 set_values[0] = 1; //0:Rx 1:Tx
1092 set_values[1] = in->app_type_cfg.app_type;
1093 set_values[2] = (long)effect_config.module_id;
1094 set_values[3] = (long)effect_config.instance_id;
1095 set_values[4] = (long)effect_config.param_id;
1096 set_values[5] = param_value;
1097
1098 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1099
1100 return 0;
1101
1102}
1103
1104static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1105 int effect_type, unsigned int *param_value)
1106{
1107 int ret = 0;
1108 struct audio_effect_config other_effect_config;
1109 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001110 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001111
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001112 if (in == NULL) {
1113 ALOGE("%s: active input stream is NULL", __func__);
1114 return -EINVAL;
1115 }
1116
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001117 usecase = get_usecase_from_list(adev, in->usecase);
1118 if (!usecase)
1119 return -EINVAL;
1120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1122 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1123 if (ret < 0) {
1124 ALOGE("%s Failed to get effect params %d", __func__, ret);
1125 return ret;
1126 }
1127
1128 if (module_id == other_effect_config.module_id) {
1129 //Same module id for AEC/NS. Values need to be combined
1130 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1131 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1132 *param_value |= other_effect_config.param_value;
1133 }
1134 }
1135
1136 return ret;
1137}
1138
1139static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301140{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001141 struct audio_effect_config effect_config;
1142 struct audio_usecase *usecase = NULL;
1143 int ret = 0;
1144 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001145 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001146
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001147 if(!voice_extn_is_dynamic_ecns_enabled())
1148 return ENOSYS;
1149
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150 if (!in) {
1151 ALOGE("%s: Invalid input stream", __func__);
1152 return -EINVAL;
1153 }
1154
1155 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1156
1157 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001158 if (usecase == NULL) {
1159 ALOGE("%s: Could not find the usecase (%d) in the list",
1160 __func__, in->usecase);
1161 return -EINVAL;
1162 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
1164 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1165 if (ret < 0) {
1166 ALOGE("%s Failed to get module id %d", __func__, ret);
1167 return ret;
1168 }
1169 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1170 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1171
1172 if(enable)
1173 param_value = effect_config.param_value;
1174
1175 /*Special handling for AEC & NS effects Param values need to be
1176 updated if module ids are same*/
1177
1178 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1179 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1180 if (ret < 0)
1181 return ret;
1182 }
1183
1184 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1185
1186 return ret;
1187}
1188
1189static void check_and_enable_effect(struct audio_device *adev)
1190{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001191 if(!voice_extn_is_dynamic_ecns_enabled())
1192 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001193
Eric Laurent637e2d42018-11-15 12:24:31 -08001194 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001195
Eric Laurent637e2d42018-11-15 12:24:31 -08001196 if (in != NULL && !in->standby) {
1197 if (in->enable_aec)
1198 enable_disable_effect(adev, EFFECT_AEC, true);
1199
1200 if (in->enable_ns &&
1201 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1202 enable_disable_effect(adev, EFFECT_NS, true);
1203 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204 }
1205}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001206
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001207int pcm_ioctl(struct pcm *pcm, int request, ...)
1208{
1209 va_list ap;
1210 void * arg;
1211 int pcm_fd = *(int*)pcm;
1212
1213 va_start(ap, request);
1214 arg = va_arg(ap, void *);
1215 va_end(ap);
1216
1217 return ioctl(pcm_fd, request, arg);
1218}
1219
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001220int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001221 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001224 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301225 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301226 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001227 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301228 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001229
1230 if (usecase == NULL)
1231 return -EINVAL;
1232
1233 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1234
Carter Hsu2e429db2019-05-14 18:50:52 +08001235 if (usecase->type == PCM_CAPTURE) {
1236 struct stream_in *in = usecase->stream.in;
1237 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001239
1240 if (in) {
1241 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001242 list_init(&out_devices);
1243 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001244 struct listnode *node;
1245 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1246 USECASE_AUDIO_PLAYBACK_VOIP);
1247 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001248 assign_devices(&out_devices,
1249 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001250 } else if (adev->primary_output &&
1251 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001252 assign_devices(&out_devices,
1253 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001254 } else {
1255 list_for_each(node, &adev->usecase_list) {
1256 uinfo = node_to_item(node, struct audio_usecase, list);
1257 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001258 assign_devices(&out_devices,
1259 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001260 break;
1261 }
1262 }
1263 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001264
1265 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001266 in->ec_opened = true;
1267 }
1268 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001269 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1270 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1271 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001272 snd_device = usecase->in_snd_device;
1273 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001275 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001276
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001277#ifdef DS1_DOLBY_DAP_ENABLED
1278 audio_extn_dolby_set_dmid(adev);
1279 audio_extn_dolby_set_endpoint(adev);
1280#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001281 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001282 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301283 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001284 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001285 if (audio_extn_is_maxx_audio_enabled())
1286 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301287 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001288 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1289 out = usecase->stream.out;
1290 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301291 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1292 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301293
1294 if (usecase->type == PCM_CAPTURE) {
1295 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001296 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301297 ALOGD("%s: set custom mtmx params v1", __func__);
1298 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1299 }
1300 } else {
1301 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1302 }
Manish Dewangan58229382017-02-02 15:48:41 +05301303
Andy Hung756ecc12018-10-19 17:47:12 -07001304 // we shouldn't truncate mixer_path
1305 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1306 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1307 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001308 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001309 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301310 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1311 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1312 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1313 if (parms) {
1314 audio_extn_fm_set_parameters(adev, parms);
1315 str_parms_destroy(parms);
1316 }
1317 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 ALOGV("%s: exit", __func__);
1319 return 0;
1320}
1321
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001322int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001323 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001326 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001328
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301329 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001330 return -EINVAL;
1331
1332 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301333 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334 snd_device = usecase->in_snd_device;
1335 else
1336 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001337
1338 /* disable island and power mode on supported device for voice call */
1339 if (usecase->type == VOICE_CALL) {
1340 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1341 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1342 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1343 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1344 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1345 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001346 if (voice_is_lte_call_active(adev))
1347 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001348 ALOGD("%s: disable island cfg and power mode in voice tx path",
1349 __func__);
1350 }
1351 }
1352 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1353 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1354 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1355 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1356 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1357 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1358 ALOGD("%s: disable island cfg and power mode in voice rx path",
1359 __func__);
1360 }
1361 }
1362 }
1363
Andy Hung756ecc12018-10-19 17:47:12 -07001364 // we shouldn't truncate mixer_path
1365 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1366 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1367 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001368 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001369 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001370 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001371 if (usecase->type == PCM_CAPTURE) {
1372 struct stream_in *in = usecase->stream.in;
1373 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001374 struct listnode out_devices;
1375 list_init(&out_devices);
1376 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001377 in->ec_opened = false;
1378 }
1379 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001380 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301381 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301382
1383 if (usecase->type == PCM_CAPTURE) {
1384 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001385 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301386 ALOGD("%s: reset custom mtmx params v1", __func__);
1387 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1388 }
1389 } else {
1390 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1391 }
1392
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001393 if ((usecase->type == PCM_PLAYBACK) &&
1394 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301395 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397 ALOGV("%s: exit", __func__);
1398 return 0;
1399}
1400
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001401int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001402 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301404 int i, num_devices = 0;
1405 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001406 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1407
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001408 if (snd_device < SND_DEVICE_MIN ||
1409 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001410 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001411 return -EINVAL;
1412 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001414 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001415 ALOGE("%s: Invalid sound device returned", __func__);
1416 return -EINVAL;
1417 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001418
1419 adev->snd_dev_ref_cnt[snd_device]++;
1420
1421 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1422 (platform_split_snd_device(adev->platform,
1423 snd_device,
1424 &num_devices,
1425 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001426 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001427 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001428 /* Set backend config for A2DP to ensure slimbus configuration
1429 is correct if A2DP is already active and backend is closed
1430 and re-opened */
1431 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1432 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001433 return 0;
1434 }
1435
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001436 if (audio_extn_spkr_prot_is_enabled())
1437 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001438
Aalique Grahame22e49102018-12-18 14:23:57 -08001439 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1440
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001441 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1442 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001443 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1444 goto err;
1445 }
1446 audio_extn_dev_arbi_acquire(snd_device);
1447 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001448 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001449 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001450 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001451 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001452 } else if (platform_split_snd_device(adev->platform,
1453 snd_device,
1454 &num_devices,
1455 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301456 for (i = 0; i < num_devices; i++) {
1457 enable_snd_device(adev, new_snd_devices[i]);
1458 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001459 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001460 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001461 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301462
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001463 /* enable island and power mode on supported device */
1464 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1465 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1466 platform_set_island_cfg_on_device(adev, snd_device, true);
1467 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001468 if (voice_is_lte_call_active(adev) &&
1469 (snd_device >= SND_DEVICE_IN_BEGIN &&
1470 snd_device < SND_DEVICE_IN_END))
1471 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001472 ALOGD("%s: enable island cfg and power mode on: %s",
1473 __func__, device_name);
1474 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301475
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301476 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1477 if (audio_extn_a2dp_start_playback() < 0) {
1478 ALOGE(" fail to configure A2dp Source control path ");
1479 goto err;
1480 } else {
1481 adev->a2dp_started = true;
1482 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001483 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001484
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001485 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1486 (audio_extn_a2dp_start_capture() < 0)) {
1487 ALOGE(" fail to configure A2dp Sink control path ");
1488 goto err;
1489 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301490
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001491 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1492 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1493 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1494 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1495 ALOGE(" fail to configure sco control path ");
1496 goto err;
1497 }
Zhou Song12c29502019-03-16 10:37:18 +08001498 }
1499
Zhou Song331c8e52019-08-26 14:16:12 +08001500 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001501 /* due to the possibility of calibration overwrite between listen
1502 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001503 audio_extn_sound_trigger_update_device_status(snd_device,
1504 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301505 audio_extn_listen_update_device_status(snd_device,
1506 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001507 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001508 audio_extn_sound_trigger_update_device_status(snd_device,
1509 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301510 audio_extn_listen_update_device_status(snd_device,
1511 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001512 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001513 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001514 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001515 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301516
1517 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1518 !adev->native_playback_enabled &&
1519 audio_is_true_native_stream_active(adev)) {
1520 ALOGD("%s: %d: napb: enabling native mode in hardware",
1521 __func__, __LINE__);
1522 audio_route_apply_and_update_path(adev->audio_route,
1523 "true-native-mode");
1524 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301525 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301526 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1527 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001528 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001529 ALOGD("%s: init ec ref loopback", __func__);
1530 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1531 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534err:
1535 adev->snd_dev_ref_cnt[snd_device]--;
1536 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537}
1538
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001539int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001540 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301542 int i, num_devices = 0;
1543 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001544 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1545
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001546 if (snd_device < SND_DEVICE_MIN ||
1547 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001548 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001549 return -EINVAL;
1550 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001551
1552 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1553 ALOGE("%s: Invalid sound device returned", __func__);
1554 return -EINVAL;
1555 }
1556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1558 ALOGE("%s: device ref cnt is already 0", __func__);
1559 return -EINVAL;
1560 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001561
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001563
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001564
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001566 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301567
Aalique Grahame22e49102018-12-18 14:23:57 -08001568 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1569
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001570 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1571 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001572 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001573
1574 // when speaker device is disabled, reset swap.
1575 // will be renabled on usecase start
1576 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001577 } else if (platform_split_snd_device(adev->platform,
1578 snd_device,
1579 &num_devices,
1580 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301581 for (i = 0; i < num_devices; i++) {
1582 disable_snd_device(adev, new_snd_devices[i]);
1583 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001584 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001585 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001586 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001587 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001588
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301589 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301590 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301591 adev->a2dp_started = false;
1592 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001593 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001594 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001595 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301596 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001597 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301598 adev->native_playback_enabled) {
1599 ALOGD("%s: %d: napb: disabling native mode in hardware",
1600 __func__, __LINE__);
1601 audio_route_reset_and_update_path(adev->audio_route,
1602 "true-native-mode");
1603 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001604 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301605 adev->asrc_mode_enabled) {
1606 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301607 disable_asrc_mode(adev);
1608 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001609 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301610 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001611 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001612 ALOGD("%s: deinit ec ref loopback", __func__);
1613 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1614 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001615
1616 audio_extn_utils_release_snd_device(snd_device);
1617 } else {
1618 if (platform_split_snd_device(adev->platform,
1619 snd_device,
1620 &num_devices,
1621 new_snd_devices) == 0) {
1622 for (i = 0; i < num_devices; i++) {
1623 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1624 }
1625 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001626 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628 return 0;
1629}
1630
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001631/*
1632 legend:
1633 uc - existing usecase
1634 new_uc - new usecase
1635 d1, d11, d2 - SND_DEVICE enums
1636 a1, a2 - corresponding ANDROID device enums
1637 B1, B2 - backend strings
1638
1639case 1
1640 uc->dev d1 (a1) B1
1641 new_uc->dev d1 (a1), d2 (a2) B1, B2
1642
1643 resolution: disable and enable uc->dev on d1
1644
1645case 2
1646 uc->dev d1 (a1) B1
1647 new_uc->dev d11 (a1) B1
1648
1649 resolution: need to switch uc since d1 and d11 are related
1650 (e.g. speaker and voice-speaker)
1651 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1652
1653case 3
1654 uc->dev d1 (a1) B1
1655 new_uc->dev d2 (a2) B2
1656
1657 resolution: no need to switch uc
1658
1659case 4
1660 uc->dev d1 (a1) B1
1661 new_uc->dev d2 (a2) B1
1662
1663 resolution: disable enable uc-dev on d2 since backends match
1664 we cannot enable two streams on two different devices if they
1665 share the same backend. e.g. if offload is on speaker device using
1666 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1667 using the same backend, offload must also be switched to voice-handset.
1668
1669case 5
1670 uc->dev d1 (a1) B1
1671 new_uc->dev d1 (a1), d2 (a2) B1
1672
1673 resolution: disable enable uc-dev on d2 since backends match
1674 we cannot enable two streams on two different devices if they
1675 share the same backend.
1676
1677case 6
1678 uc->dev d1 (a1) B1
1679 new_uc->dev d2 (a1) B2
1680
1681 resolution: no need to switch
1682
1683case 7
1684 uc->dev d1 (a1), d2 (a2) B1, B2
1685 new_uc->dev d1 (a1) B1
1686
1687 resolution: no need to switch
1688
Zhou Song4ba65882018-07-09 14:48:07 +08001689case 8
1690 uc->dev d1 (a1) B1
1691 new_uc->dev d11 (a1), d2 (a2) B1, B2
1692 resolution: compared to case 1, for this case, d1 and d11 are related
1693 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301694
1695case 9
1696 uc->dev d1 (a1), d2(a2) B1 B2
1697 new_uc->dev d1 (a1), d22 (a2) B1, B2
1698 resolution: disable enable uc-dev on d2 since backends match
1699 we cannot enable two streams on two different devices if they
1700 share the same backend. This is special case for combo use case
1701 with a2dp and sco devices which uses same backend.
1702 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001703*/
1704static snd_device_t derive_playback_snd_device(void * platform,
1705 struct audio_usecase *uc,
1706 struct audio_usecase *new_uc,
1707 snd_device_t new_snd_device)
1708{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001709 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001710
1711 snd_device_t d1 = uc->out_snd_device;
1712 snd_device_t d2 = new_snd_device;
1713
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001714 list_init(&a1);
1715 list_init(&a2);
1716
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301717 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301718 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001719 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1720 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301721 break;
1722 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001723 assign_devices(&a1, &uc->stream.out->device_list);
1724 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301725 break;
1726 }
1727
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001728 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001729 if (!compare_devices(&a1, &a2) &&
1730 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001731 snd_device_t d3[2];
1732 int num_devices = 0;
1733 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001734 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001735 &num_devices,
1736 d3);
1737 if (ret < 0) {
1738 if (ret != -ENOSYS) {
1739 ALOGW("%s failed to split snd_device %d",
1740 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001741 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001742 }
1743 goto end;
1744 }
1745
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001746 if (platform_check_backends_match(d3[0], d3[1])) {
1747 return d2; // case 5
1748 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301749 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1750 platform_check_backends_match(d1, d2))
1751 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001752 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301753 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001754 // check if d1 is related to any of d3's
1755 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001756 return d1; // case 1
1757 else
1758 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001759 }
1760 } else {
1761 if (platform_check_backends_match(d1, d2)) {
1762 return d2; // case 2, 4
1763 } else {
1764 return d1; // case 6, 3
1765 }
1766 }
1767
1768end:
1769 return d2; // return whatever was calculated before.
1770}
1771
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001772static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301773 struct audio_usecase *uc_info,
1774 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775{
1776 struct listnode *node;
1777 struct audio_usecase *usecase;
1778 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301779 snd_device_t uc_derive_snd_device;
1780 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001781 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1782 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001783 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301784 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 /*
1786 * This function is to make sure that all the usecases that are active on
1787 * the hardware codec backend are always routed to any one device that is
1788 * handled by the hardware codec.
1789 * For example, if low-latency and deep-buffer usecases are currently active
1790 * on speaker and out_set_parameters(headset) is received on low-latency
1791 * output, then we have to make sure deep-buffer is also switched to headset,
1792 * because of the limitation that both the devices cannot be enabled
1793 * at the same time as they share the same backend.
1794 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001795 /*
1796 * This call is to check if we need to force routing for a particular stream
1797 * If there is a backend configuration change for the device when a
1798 * new stream starts, then ADM needs to be closed and re-opened with the new
1799 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001800 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001801 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001802 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1803 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301804 /* For a2dp device reconfigure all active sessions
1805 * with new AFE encoder format based on a2dp state
1806 */
1807 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301808 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1809 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301810 audio_extn_a2dp_is_force_device_switch()) {
1811 force_routing = true;
1812 force_restart_session = true;
1813 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001814
1815 /*
1816 * Island cfg and power mode config needs to set before AFE port start.
1817 * Set force routing in case of voice device was enable before.
1818 */
1819 if (uc_info->type == VOICE_CALL &&
1820 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001821 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001822 platform_check_and_update_island_power_status(adev->platform,
1823 uc_info,
1824 snd_device)) {
1825 force_routing = true;
1826 ALOGD("%s:becf: force routing %d for power mode supported device",
1827 __func__, force_routing);
1828 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301829 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001832 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001833 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1835 switch_device[i] = false;
1836
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001839
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301840 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1841 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301842 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301843 platform_get_snd_device_name(usecase->out_snd_device),
1844 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301845 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1846 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301847 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1848 usecase, uc_info, snd_device);
1849 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001850 (is_codec_backend_out_device_type(&usecase->device_list) ||
1851 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1852 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1853 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1854 is_a2dp_out_device_type(&usecase->device_list) ||
1855 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301856 ((force_restart_session) ||
1857 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301858 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1859 __func__, use_case_table[usecase->id],
1860 platform_get_snd_device_name(usecase->out_snd_device));
1861 disable_audio_route(adev, usecase);
1862 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301863 /* Enable existing usecase on derived playback device */
1864 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301865 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 }
1868 }
1869
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301870 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1871 num_uc_to_switch);
1872
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001874 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301876 /* Make sure the previous devices to be disabled first and then enable the
1877 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 list_for_each(node, &adev->usecase_list) {
1879 usecase = node_to_item(node, struct audio_usecase, list);
1880 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001881 /* Check if output sound device to be switched can be split and if any
1882 of the split devices match with derived sound device */
1883 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1884 &num_devices, split_snd_devices) == 0) {
1885 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1886 for (i = 0; i < num_devices; i++) {
1887 /* Disable devices that do not match with derived sound device */
1888 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1889 disable_snd_device(adev, split_snd_devices[i]);
1890 }
1891 } else {
1892 disable_snd_device(adev, usecase->out_snd_device);
1893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 }
1895 }
1896
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001900 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1901 &num_devices, split_snd_devices) == 0) {
1902 /* Enable derived sound device only if it does not match with
1903 one of the split sound devices. This is because the matching
1904 sound device was not disabled */
1905 bool should_enable = true;
1906 for (i = 0; i < num_devices; i++) {
1907 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1908 should_enable = false;
1909 break;
1910 }
1911 }
1912 if (should_enable)
1913 enable_snd_device(adev, derive_snd_device[usecase->id]);
1914 } else {
1915 enable_snd_device(adev, derive_snd_device[usecase->id]);
1916 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001917 }
1918 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001920 /* Re-route all the usecases on the shared backend other than the
1921 specified usecase to new snd devices */
1922 list_for_each(node, &adev->usecase_list) {
1923 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301924 /* Update the out_snd_device only before enabling the audio route */
1925 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301926 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301927 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1928 use_case_table[usecase->id],
1929 platform_get_snd_device_name(usecase->out_snd_device));
1930 /* Update voc calibration before enabling Voice/VoIP route */
1931 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1932 status = platform_switch_voice_call_device_post(adev->platform,
1933 usecase->out_snd_device,
1934 platform_get_input_snd_device(
1935 adev->platform, NULL,
1936 &uc_info->device_list,
1937 usecase->type));
1938 enable_audio_route(adev, usecase);
1939 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1940 out_set_voip_volume(&usecase->stream.out->stream,
1941 usecase->stream.out->volume_l,
1942 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001944 }
1945 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001946 }
1947}
1948
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301949static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001950 struct audio_usecase *uc_info,
1951 snd_device_t snd_device)
1952{
1953 struct listnode *node;
1954 struct audio_usecase *usecase;
1955 bool switch_device[AUDIO_USECASE_MAX];
1956 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001957 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001958 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001959
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301960 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1961 snd_device);
1962 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301963
1964 /*
1965 * Make sure out devices is checked against out codec backend device and
1966 * also in devices against in codec backend. Checking out device against in
1967 * codec backend or vice versa causes issues.
1968 */
1969 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001970 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001971
1972 /*
1973 * Island cfg and power mode config needs to set before AFE port start.
1974 * Set force routing in case of voice device was enable before.
1975 */
1976
1977 if (uc_info->type == VOICE_CALL &&
1978 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001979 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001980 platform_check_and_update_island_power_status(adev->platform,
1981 uc_info,
1982 snd_device)) {
1983 force_routing = true;
1984 ALOGD("%s:becf: force routing %d for power mode supported device",
1985 __func__, force_routing);
1986 }
1987
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001988 /*
1989 * This function is to make sure that all the active capture usecases
1990 * are always routed to the same input sound device.
1991 * For example, if audio-record and voice-call usecases are currently
1992 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1993 * is received for voice call then we have to make sure that audio-record
1994 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1995 * because of the limitation that two devices cannot be enabled
1996 * at the same time if they share the same backend.
1997 */
1998 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1999 switch_device[i] = false;
2000
2001 list_for_each(node, &adev->usecase_list) {
2002 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302003 /*
2004 * TODO: Enhance below condition to handle BT sco/USB multi recording
2005 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302006
2007 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2008 (usecase->in_snd_device != snd_device || force_routing));
2009 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2010 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2011 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002012 ((backend_check_cond &&
2013 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002014 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002015 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002016 is_single_device_type_equal(&usecase->device_list,
2017 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002018 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002019 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002020 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302021 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002022 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002023 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002024 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002025 switch_device[usecase->id] = true;
2026 num_uc_to_switch++;
2027 }
2028 }
2029
2030 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002031 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002032
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302033 /* Make sure the previous devices to be disabled first and then enable the
2034 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002035 list_for_each(node, &adev->usecase_list) {
2036 usecase = node_to_item(node, struct audio_usecase, list);
2037 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002038 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002039 }
2040 }
2041
2042 list_for_each(node, &adev->usecase_list) {
2043 usecase = node_to_item(node, struct audio_usecase, list);
2044 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002045 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002046 }
2047 }
2048
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002049 /* Re-route all the usecases on the shared backend other than the
2050 specified usecase to new snd devices */
2051 list_for_each(node, &adev->usecase_list) {
2052 usecase = node_to_item(node, struct audio_usecase, list);
2053 /* Update the in_snd_device only before enabling the audio route */
2054 if (switch_device[usecase->id] ) {
2055 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302056 /* Update voc calibration before enabling Voice/VoIP route */
2057 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2058 snd_device_t voip_snd_device;
2059 voip_snd_device = platform_get_output_snd_device(adev->platform,
2060 usecase->stream.out,
2061 usecase->type);
2062 status = platform_switch_voice_call_device_post(adev->platform,
2063 voip_snd_device,
2064 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002065 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302066 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002067 }
2068 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002069 }
2070}
2071
Mingming Yin3a941d42016-02-17 18:08:05 -08002072static void reset_hdmi_sink_caps(struct stream_out *out) {
2073 int i = 0;
2074
2075 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2076 out->supported_channel_masks[i] = 0;
2077 }
2078 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2079 out->supported_formats[i] = 0;
2080 }
2081 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2082 out->supported_sample_rates[i] = 0;
2083 }
2084}
2085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002087static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088{
Mingming Yin3a941d42016-02-17 18:08:05 -08002089 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002090 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2091 out->extconn.cs.controller,
2092 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093
Mingming Yin3a941d42016-02-17 18:08:05 -08002094 reset_hdmi_sink_caps(out);
2095
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002096 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002097 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002098 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002099 out->extconn.cs.stream);
2100 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002101 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002102 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002103 }
2104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002107 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002108 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002109 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2110 case 6:
2111 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2112 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2113 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2114 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2115 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2116 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 break;
2118 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002119 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002120 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 break;
2122 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002123
2124 // check channel format caps
2125 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002126 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2127 out->extconn.cs.controller,
2128 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002129 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2130 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2131 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2132 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2133 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2134 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2135 }
2136
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002137 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2138 out->extconn.cs.controller,
2139 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002140 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2141 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2142 }
2143
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002144 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2145 out->extconn.cs.controller,
2146 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002147 ALOGV(":%s HDMI supports DTS format", __func__);
2148 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2149 }
2150
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002151 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2152 out->extconn.cs.controller,
2153 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002154 ALOGV(":%s HDMI supports DTS HD format", __func__);
2155 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2156 }
2157
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002158 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2159 out->extconn.cs.controller,
2160 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002161 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2162 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2163 }
2164
Mingming Yin3a941d42016-02-17 18:08:05 -08002165
2166 // check sample rate caps
2167 i = 0;
2168 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002169 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2170 out->extconn.cs.controller,
2171 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002172 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2173 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2174 }
2175 }
2176
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002177 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178}
2179
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002180static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2181 uint32_t *supported_sample_rates __unused,
2182 uint32_t max_rates __unused)
2183{
2184 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2185 supported_sample_rates,
2186 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302187 ssize_t i = 0;
2188
2189 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002190 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2191 supported_sample_rates[i]);
2192 }
2193 return count;
2194}
2195
2196static inline int read_usb_sup_channel_masks(bool is_playback,
2197 audio_channel_mask_t *supported_channel_masks,
2198 uint32_t max_masks)
2199{
2200 int channels = audio_extn_usb_get_max_channels(is_playback);
2201 int channel_count;
2202 uint32_t num_masks = 0;
2203 if (channels > MAX_HIFI_CHANNEL_COUNT)
2204 channels = MAX_HIFI_CHANNEL_COUNT;
2205
2206 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002207 // start from 2 channels as framework currently doesn't support mono.
2208 if (channels >= FCC_2) {
2209 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2210 }
2211 for (channel_count = FCC_2;
2212 channel_count <= channels && num_masks < max_masks;
2213 ++channel_count) {
2214 supported_channel_masks[num_masks++] =
2215 audio_channel_mask_for_index_assignment_from_count(channel_count);
2216 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002217 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002218 // For capture we report all supported channel masks from 1 channel up.
2219 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002220 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2221 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002222 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2223 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2224 if (channel_count <= FCC_2) {
2225 mask = audio_channel_in_mask_from_count(channel_count);
2226 supported_channel_masks[num_masks++] = mask;
2227 }
2228 const audio_channel_mask_t index_mask =
2229 audio_channel_mask_for_index_assignment_from_count(channel_count);
2230 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2231 supported_channel_masks[num_masks++] = index_mask;
2232 }
2233 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002234 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302235
vincenttewf51c94e2019-05-07 10:28:53 +08002236 for (size_t i = 0; i < num_masks; ++i) {
2237 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2238 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302239 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002240 return num_masks;
2241}
2242
2243static inline int read_usb_sup_formats(bool is_playback __unused,
2244 audio_format_t *supported_formats,
2245 uint32_t max_formats __unused)
2246{
2247 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2248 switch (bitwidth) {
2249 case 24:
2250 // XXX : usb.c returns 24 for s24 and s24_le?
2251 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2252 break;
2253 case 32:
2254 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2255 break;
2256 case 16:
2257 default :
2258 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2259 break;
2260 }
2261 ALOGV("%s: %s supported format %d", __func__,
2262 is_playback ? "P" : "C", bitwidth);
2263 return 1;
2264}
2265
2266static inline int read_usb_sup_params_and_compare(bool is_playback,
2267 audio_format_t *format,
2268 audio_format_t *supported_formats,
2269 uint32_t max_formats,
2270 audio_channel_mask_t *mask,
2271 audio_channel_mask_t *supported_channel_masks,
2272 uint32_t max_masks,
2273 uint32_t *rate,
2274 uint32_t *supported_sample_rates,
2275 uint32_t max_rates) {
2276 int ret = 0;
2277 int num_formats;
2278 int num_masks;
2279 int num_rates;
2280 int i;
2281
2282 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2283 max_formats);
2284 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2285 max_masks);
2286
2287 num_rates = read_usb_sup_sample_rates(is_playback,
2288 supported_sample_rates, max_rates);
2289
2290#define LUT(table, len, what, dflt) \
2291 for (i=0; i<len && (table[i] != what); i++); \
2292 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2293
2294 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2295 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2296 LUT(supported_sample_rates, num_rates, *rate, 0);
2297
2298#undef LUT
2299 return ret < 0 ? -EINVAL : 0; // HACK TBD
2300}
2301
Alexy Josephb1379942016-01-29 15:49:38 -08002302audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002303 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002304{
2305 struct audio_usecase *usecase;
2306 struct listnode *node;
2307
2308 list_for_each(node, &adev->usecase_list) {
2309 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002310 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002311 ALOGV("%s: usecase id %d", __func__, usecase->id);
2312 return usecase->id;
2313 }
2314 }
2315 return USECASE_INVALID;
2316}
2317
Alexy Josephb1379942016-01-29 15:49:38 -08002318struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002319 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002320{
2321 struct audio_usecase *usecase;
2322 struct listnode *node;
2323
2324 list_for_each(node, &adev->usecase_list) {
2325 usecase = node_to_item(node, struct audio_usecase, list);
2326 if (usecase->id == uc_id)
2327 return usecase;
2328 }
2329 return NULL;
2330}
2331
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302332/*
2333 * is a true native playback active
2334 */
2335bool audio_is_true_native_stream_active(struct audio_device *adev)
2336{
2337 bool active = false;
2338 int i = 0;
2339 struct listnode *node;
2340
2341 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2342 ALOGV("%s:napb: not in true mode or non hdphones device",
2343 __func__);
2344 active = false;
2345 goto exit;
2346 }
2347
2348 list_for_each(node, &adev->usecase_list) {
2349 struct audio_usecase *uc;
2350 uc = node_to_item(node, struct audio_usecase, list);
2351 struct stream_out *curr_out =
2352 (struct stream_out*) uc->stream.out;
2353
2354 if (curr_out && PCM_PLAYBACK == uc->type) {
2355 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2356 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2357 uc->id, curr_out->sample_rate,
2358 curr_out->bit_width,
2359 platform_get_snd_device_name(uc->out_snd_device));
2360
2361 if (is_offload_usecase(uc->id) &&
2362 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2363 active = true;
2364 ALOGD("%s:napb:native stream detected", __func__);
2365 }
2366 }
2367 }
2368exit:
2369 return active;
2370}
2371
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002372uint32_t adev_get_dsp_bit_width_enforce_mode()
2373{
2374 if (adev == NULL) {
2375 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2376 return 0;
2377 }
2378 return adev->dsp_bit_width_enforce_mode;
2379}
2380
2381static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2382{
2383 char value[PROPERTY_VALUE_MAX];
2384 int trial;
2385 uint32_t dsp_bit_width_enforce_mode = 0;
2386
2387 if (!mixer) {
2388 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2389 __func__);
2390 return 0;
2391 }
2392
2393 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2394 value, NULL) > 0) {
2395 trial = atoi(value);
2396 switch (trial) {
2397 case 16:
2398 dsp_bit_width_enforce_mode = 16;
2399 break;
2400 case 24:
2401 dsp_bit_width_enforce_mode = 24;
2402 break;
2403 case 32:
2404 dsp_bit_width_enforce_mode = 32;
2405 break;
2406 default:
2407 dsp_bit_width_enforce_mode = 0;
2408 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2409 break;
2410 }
2411 }
2412
2413 return dsp_bit_width_enforce_mode;
2414}
2415
2416static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2417 uint32_t enforce_mode,
2418 bool enable)
2419{
2420 struct mixer_ctl *ctl = NULL;
2421 const char *mixer_ctl_name = "ASM Bit Width";
2422 uint32_t asm_bit_width_mode = 0;
2423
2424 if (enforce_mode == 0) {
2425 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2426 return;
2427 }
2428
2429 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2430 if (!ctl) {
2431 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2432 __func__, mixer_ctl_name);
2433 return;
2434 }
2435
2436 if (enable)
2437 asm_bit_width_mode = enforce_mode;
2438 else
2439 asm_bit_width_mode = 0;
2440
2441 ALOGV("%s DSP bit width feature status is %d width=%d",
2442 __func__, enable, asm_bit_width_mode);
2443 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2444 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2445 asm_bit_width_mode);
2446
2447 return;
2448}
2449
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302450/*
2451 * if native DSD playback active
2452 */
2453bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2454{
2455 bool active = false;
2456 struct listnode *node = NULL;
2457 struct audio_usecase *uc = NULL;
2458 struct stream_out *curr_out = NULL;
2459
2460 list_for_each(node, &adev->usecase_list) {
2461 uc = node_to_item(node, struct audio_usecase, list);
2462 curr_out = (struct stream_out*) uc->stream.out;
2463
2464 if (curr_out && PCM_PLAYBACK == uc->type &&
2465 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2466 active = true;
2467 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302468 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302469 }
2470 }
2471 return active;
2472}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302473
2474static bool force_device_switch(struct audio_usecase *usecase)
2475{
2476 bool ret = false;
2477 bool is_it_true_mode = false;
2478
Zhou Song30f2c3e2018-02-08 14:02:15 +08002479 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302480 usecase->type == TRANSCODE_LOOPBACK_RX ||
2481 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002482 return false;
2483 }
2484
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002485 if(usecase->stream.out == NULL) {
2486 ALOGE("%s: stream.out is NULL", __func__);
2487 return false;
2488 }
2489
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302490 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002491 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002492 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2493 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302494 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2495 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2496 (!is_it_true_mode && adev->native_playback_enabled)){
2497 ret = true;
2498 ALOGD("napb: time to toggle native mode");
2499 }
2500 }
2501
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302502 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302503 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2504 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002505 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302506 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302507 ALOGD("Force a2dp device switch to update new encoder config");
2508 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002509 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302510
Florian Pfister1a84f312018-07-19 14:38:18 +02002511 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302512 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2513 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002514 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302515 return ret;
2516}
2517
Aalique Grahame22e49102018-12-18 14:23:57 -08002518static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2519{
2520 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2521}
2522
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302523bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2524{
2525 bool ret=false;
2526 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002527 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2528 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302529 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2530 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002531 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302532 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002533 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2534 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302535 ret = true;
2536
2537 return ret;
2538}
2539
2540bool is_a2dp_device(snd_device_t out_snd_device)
2541{
2542 bool ret=false;
2543 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2544 ret = true;
2545
2546 return ret;
2547}
2548
2549bool is_bt_soc_on(struct audio_device *adev)
2550{
2551 struct mixer_ctl *ctl;
2552 char *mixer_ctl_name = "BT SOC status";
2553 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2554 bool bt_soc_status = true;
2555 if (!ctl) {
2556 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2557 __func__, mixer_ctl_name);
2558 /*This is to ensure we dont break targets which dont have the kernel change*/
2559 return true;
2560 }
2561 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2562 ALOGD("BT SOC status: %d",bt_soc_status);
2563 return bt_soc_status;
2564}
2565
Zhou Song331c8e52019-08-26 14:16:12 +08002566static int configure_btsco_sample_rate(snd_device_t snd_device)
2567{
2568 struct mixer_ctl *ctl = NULL;
2569 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2570 char *rate_str = NULL;
2571 bool is_rx_dev = true;
2572
2573 if (is_btsco_device(snd_device, snd_device)) {
2574 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2575 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2576 if (!ctl_sr_tx || !ctl_sr_rx) {
2577 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2578 if (!ctl_sr)
2579 return -ENOSYS;
2580 }
2581
2582 switch (snd_device) {
2583 case SND_DEVICE_OUT_BT_SCO:
2584 rate_str = "KHZ_8";
2585 break;
2586 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2587 case SND_DEVICE_IN_BT_SCO_MIC:
2588 rate_str = "KHZ_8";
2589 is_rx_dev = false;
2590 break;
2591 case SND_DEVICE_OUT_BT_SCO_WB:
2592 rate_str = "KHZ_16";
2593 break;
2594 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2595 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2596 rate_str = "KHZ_16";
2597 is_rx_dev = false;
2598 break;
2599 default:
2600 return 0;
2601 }
2602
2603 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2604 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2605 return -ENOSYS;
2606 }
2607 return 0;
2608}
2609
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302610int out_standby_l(struct audio_stream *stream);
2611
Eric Laurent637e2d42018-11-15 12:24:31 -08002612struct stream_in *adev_get_active_input(const struct audio_device *adev)
2613{
2614 struct listnode *node;
2615 struct stream_in *last_active_in = NULL;
2616
2617 /* Get last added active input.
2618 * TODO: We may use a priority mechanism to pick highest priority active source */
2619 list_for_each(node, &adev->usecase_list)
2620 {
2621 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2622 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2623 last_active_in = usecase->stream.in;
2624 }
2625
2626 return last_active_in;
2627}
2628
2629struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2630{
2631 struct listnode *node;
2632
2633 /* First check active inputs with voice communication source and then
2634 * any input if audio mode is in communication */
2635 list_for_each(node, &adev->usecase_list)
2636 {
2637 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2638 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2639 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2640 return usecase->stream.in;
2641 }
2642 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2643 return adev_get_active_input(adev);
2644
2645 return NULL;
2646}
2647
Carter Hsu2e429db2019-05-14 18:50:52 +08002648/*
2649 * Aligned with policy.h
2650 */
2651static inline int source_priority(int inputSource)
2652{
2653 switch (inputSource) {
2654 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2655 return 9;
2656 case AUDIO_SOURCE_CAMCORDER:
2657 return 8;
2658 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2659 return 7;
2660 case AUDIO_SOURCE_UNPROCESSED:
2661 return 6;
2662 case AUDIO_SOURCE_MIC:
2663 return 5;
2664 case AUDIO_SOURCE_ECHO_REFERENCE:
2665 return 4;
2666 case AUDIO_SOURCE_FM_TUNER:
2667 return 3;
2668 case AUDIO_SOURCE_VOICE_RECOGNITION:
2669 return 2;
2670 case AUDIO_SOURCE_HOTWORD:
2671 return 1;
2672 default:
2673 break;
2674 }
2675 return 0;
2676}
2677
2678static struct stream_in *get_priority_input(struct audio_device *adev)
2679{
2680 struct listnode *node;
2681 struct audio_usecase *usecase;
2682 int last_priority = 0, priority;
2683 struct stream_in *priority_in = NULL;
2684 struct stream_in *in;
2685
2686 list_for_each(node, &adev->usecase_list) {
2687 usecase = node_to_item(node, struct audio_usecase, list);
2688 if (usecase->type == PCM_CAPTURE) {
2689 in = usecase->stream.in;
2690 if (!in)
2691 continue;
2692 priority = source_priority(in->source);
2693
2694 if (priority > last_priority) {
2695 last_priority = priority;
2696 priority_in = in;
2697 }
2698 }
2699 }
2700 return priority_in;
2701}
2702
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002703int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002705 snd_device_t out_snd_device = SND_DEVICE_NONE;
2706 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002707 struct audio_usecase *usecase = NULL;
2708 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002709 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002710 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302711 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002712 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002713 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302715 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2716
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002717 usecase = get_usecase_from_list(adev, uc_id);
2718 if (usecase == NULL) {
2719 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2720 return -EINVAL;
2721 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002723 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002724 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002725 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002726 (usecase->type == ICC_CALL) ||
2727 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302728 if(usecase->stream.out == NULL) {
2729 ALOGE("%s: stream.out is NULL", __func__);
2730 return -EINVAL;
2731 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002732 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002733 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2734 uc_id);
2735 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2736 uc_id);
2737 } else {
2738 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302739 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002740 in_snd_device = platform_get_input_snd_device(adev->platform,
2741 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302742 &usecase->stream.out->device_list,
2743 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002744 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002745 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302746 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302747 if (usecase->stream.inout == NULL) {
2748 ALOGE("%s: stream.inout is NULL", __func__);
2749 return -EINVAL;
2750 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002751 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302752 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2753 stream_out.format = usecase->stream.inout->out_config.format;
2754 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302755 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002756 assign_devices(&usecase->device_list,
2757 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302758 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2759 if (usecase->stream.inout == NULL) {
2760 ALOGE("%s: stream.inout is NULL", __func__);
2761 return -EINVAL;
2762 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302763 struct listnode out_devices;
2764 list_init(&out_devices);
2765 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2766 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002767 assign_devices(&usecase->device_list,
2768 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002769 } else {
2770 /*
2771 * If the voice call is active, use the sound devices of voice call usecase
2772 * so that it would not result any device switch. All the usecases will
2773 * be switched to new device when select_devices() is called for voice call
2774 * usecase. This is to avoid switching devices for voice call when
2775 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002776 * choose voice call device only if the use case device is
2777 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002778 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002779 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002780 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002781 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002782 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2783 is_codec_backend_out_device_type(&usecase->device_list)) ||
2784 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2785 is_codec_backend_in_device_type(&usecase->device_list)) ||
2786 is_single_device_type_equal(&vc_usecase->device_list,
2787 AUDIO_DEVICE_OUT_HEARING_AID) ||
2788 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002789 AUDIO_DEVICE_IN_VOICE_CALL) ||
2790 (is_single_device_type_equal(&usecase->device_list,
2791 AUDIO_DEVICE_IN_USB_HEADSET) &&
2792 is_single_device_type_equal(&vc_usecase->device_list,
2793 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002794 in_snd_device = vc_usecase->in_snd_device;
2795 out_snd_device = vc_usecase->out_snd_device;
2796 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002797 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002798 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002799 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002800 if ((voip_usecase != NULL) &&
2801 (usecase->type == PCM_PLAYBACK) &&
2802 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002803 out_snd_device_backend_match = platform_check_backends_match(
2804 voip_usecase->out_snd_device,
2805 platform_get_output_snd_device(
2806 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302807 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002808 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002809 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2810 (is_codec_backend_out_device_type(&usecase->device_list) ||
2811 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002812 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002813 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002814 in_snd_device = voip_usecase->in_snd_device;
2815 out_snd_device = voip_usecase->out_snd_device;
2816 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002817 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002818 hfp_ucid = audio_extn_hfp_get_usecase();
2819 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002820 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002821 in_snd_device = hfp_usecase->in_snd_device;
2822 out_snd_device = hfp_usecase->out_snd_device;
2823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002824 }
2825 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302826 if (usecase->stream.out == NULL) {
2827 ALOGE("%s: stream.out is NULL", __func__);
2828 return -EINVAL;
2829 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002830 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002831 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002832 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002833 struct stream_out *voip_out = adev->primary_output;
2834 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002835 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002836 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2837 else
2838 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302839 usecase->stream.out,
2840 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002841 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002842
Eric Laurent637e2d42018-11-15 12:24:31 -08002843 if (voip_usecase)
2844 voip_out = voip_usecase->stream.out;
2845
2846 if (usecase->stream.out == voip_out && voip_in != NULL)
2847 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002848 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002849 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302850 if (usecase->stream.in == NULL) {
2851 ALOGE("%s: stream.in is NULL", __func__);
2852 return -EINVAL;
2853 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002854 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002855 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002856 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002857 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002858 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002859 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002860
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002861 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002862 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002863 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2864 USECASE_AUDIO_PLAYBACK_VOIP);
2865
Carter Hsu2e429db2019-05-14 18:50:52 +08002866 usecase->stream.in->enable_ec_port = false;
2867
Zhou Song62ea0282020-03-22 19:53:01 +08002868 bool is_ha_usecase = adev->ha_proxy_enable ?
2869 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2870 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2871 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002872 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002873 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002874 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002875 } else if (adev->primary_output &&
2876 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002877 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002878 } else {
2879 /* forcing speaker o/p device to get matching i/p pair
2880 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002881 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002882 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002883 priority_in = voip_in;
2884 } else {
2885 /* get the input with the highest priority source*/
2886 priority_in = get_priority_input(adev);
2887
2888 if (!priority_in)
2889 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002890 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002891 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2892 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2893 }
2894 else
2895 in_snd_device = platform_get_input_snd_device(adev->platform,
2896 priority_in,
2897 &out_devices,
2898 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002900 }
2901 }
2902
2903 if (out_snd_device == usecase->out_snd_device &&
2904 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302905
2906 if (!force_device_switch(usecase))
2907 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 }
2909
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002910 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002911 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002912 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002913 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2914 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302915 }
2916
Aalique Grahame22e49102018-12-18 14:23:57 -08002917 if (out_snd_device != SND_DEVICE_NONE &&
2918 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2919 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2920 __func__,
2921 use_case_table[uc_id],
2922 adev->last_logged_snd_device[uc_id][0],
2923 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2924 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2925 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2926 -1,
2927 out_snd_device,
2928 platform_get_snd_device_name(out_snd_device),
2929 platform_get_snd_device_acdb_id(out_snd_device));
2930 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2931 }
2932 if (in_snd_device != SND_DEVICE_NONE &&
2933 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2934 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2935 __func__,
2936 use_case_table[uc_id],
2937 adev->last_logged_snd_device[uc_id][1],
2938 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2939 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2940 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2941 -1,
2942 in_snd_device,
2943 platform_get_snd_device_name(in_snd_device),
2944 platform_get_snd_device_acdb_id(in_snd_device));
2945 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2946 }
2947
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 /*
2950 * Limitation: While in call, to do a device switch we need to disable
2951 * and enable both RX and TX devices though one of them is same as current
2952 * device.
2953 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002954 if ((usecase->type == VOICE_CALL) &&
2955 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2956 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002957 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002958 }
2959
2960 if (((usecase->type == VOICE_CALL) ||
2961 (usecase->type == VOIP_CALL)) &&
2962 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2963 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302964 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002965 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002966 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002967
2968 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302969 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002970 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002971 }
2972
Aalique Grahame22e49102018-12-18 14:23:57 -08002973 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2974 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002975 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302976 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002977 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2978 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2979 else
2980 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302981 }
2982
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002983 /* Disable current sound devices */
2984 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002985 disable_audio_route(adev, usecase);
2986 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 }
2988
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002989 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002990 disable_audio_route(adev, usecase);
2991 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 }
2993
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002994 /* Applicable only on the targets that has external modem.
2995 * New device information should be sent to modem before enabling
2996 * the devices to reduce in-call device switch time.
2997 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002998 if ((usecase->type == VOICE_CALL) &&
2999 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3000 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003001 status = platform_switch_voice_call_enable_device_config(adev->platform,
3002 out_snd_device,
3003 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003004 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003005
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003006 /* Enable new sound devices */
3007 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003008 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303009 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303010 if (platform_check_codec_asrc_support(adev->platform))
3011 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003012 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003013 /* Enable haptics device for haptic usecase */
3014 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3015 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 }
3017
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003018 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303019 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003020 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003021 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003022
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303023 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003024 status = platform_switch_voice_call_device_post(adev->platform,
3025 out_snd_device,
3026 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003027
sangwoo170731f2013-06-08 15:36:36 +09003028 usecase->in_snd_device = in_snd_device;
3029 usecase->out_snd_device = out_snd_device;
3030
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303031 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3032 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303033 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003034 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003035 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003036 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3037 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3038 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3039 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3040 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3041 /*
3042 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3043 * configured device sample rate, if not update the COPP rate to be equal to the
3044 * device sample rate, else open COPP at stream sample rate
3045 */
3046 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3047 usecase->stream.out->sample_rate,
3048 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303049 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303050 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3051 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303052 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003053 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3054 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3055 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3056 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003057 }
3058 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003059
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003060 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003061
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003062 /* If input stream is already running then effect needs to be
3063 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003064 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003065 check_and_enable_effect(adev);
3066
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003067 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003068 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303069 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003070 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3071
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003072 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303073 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003074 voice_extn_compress_voip_is_started(adev))
3075 voice_set_sidetone(adev, out_snd_device, true);
3076 }
3077
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003078 /* Applicable only on the targets that has external modem.
3079 * Enable device command should be sent to modem only after
3080 * enabling voice call mixer controls
3081 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003082 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003083 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3084 out_snd_device,
3085 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303086
3087 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003088 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303089 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003090 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303091 if (is_bt_soc_on(adev) == false){
3092 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003093 if (in->pcm != NULL)
3094 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303095 }
3096 }
3097 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3098 && usecase->stream.out->started) {
3099 if (is_bt_soc_on(adev) == false) {
3100 ALOGD("BT SCO/A2DP disconnected while in connection");
3101 out_standby_l(&usecase->stream.out->stream.common);
3102 }
3103 }
3104 } else if ((usecase->stream.out != NULL) &&
3105 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303106 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3107 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003108 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303109 usecase->stream.out->started) {
3110 if (is_bt_soc_on(adev) == false) {
3111 ALOGD("BT SCO/A2dp disconnected while in connection");
3112 out_standby_l(&usecase->stream.out->stream.common);
3113 }
3114 }
3115 }
3116
Yung Ti Su70cb8242018-06-22 17:38:47 +08003117 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003118 struct stream_out *voip_out = voip_usecase->stream.out;
3119 audio_extn_utils_send_app_type_gain(adev,
3120 voip_out->app_type_cfg.app_type,
3121 &voip_out->app_type_cfg.gain[0]);
3122 }
3123
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003124 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 return status;
3127}
3128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129static int stop_input_stream(struct stream_in *in)
3130{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303131 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303133
3134 if (in == NULL) {
3135 ALOGE("%s: stream_in ptr is NULL", __func__);
3136 return -EINVAL;
3137 }
3138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003140 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
Eric Laurent994a6932013-07-17 11:51:42 -07003142 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003143 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 uc_info = get_usecase_from_list(adev, in->usecase);
3145 if (uc_info == NULL) {
3146 ALOGE("%s: Could not find the usecase (%d) in the list",
3147 __func__, in->usecase);
3148 return -EINVAL;
3149 }
3150
Carter Hsu2e429db2019-05-14 18:50:52 +08003151 priority_in = get_priority_input(adev);
3152
Derek Chenea197282019-01-07 17:35:01 -08003153 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3154 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003155
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003156 /* Close in-call recording streams */
3157 voice_check_and_stop_incall_rec_usecase(adev, in);
3158
Eric Laurent150dbfe2013-02-27 14:31:02 -08003159 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003160 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003161
3162 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003163 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003165 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303166 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3167
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003168 list_remove(&uc_info->list);
3169 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170
Carter Hsu2e429db2019-05-14 18:50:52 +08003171 if (priority_in == in) {
3172 priority_in = get_priority_input(adev);
3173 if (priority_in)
3174 select_devices(adev, priority_in->usecase);
3175 }
3176
Vatsal Buchac09ae062018-11-14 13:25:08 +05303177 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003178 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 return ret;
3180}
3181
3182int start_input_stream(struct stream_in *in)
3183{
3184 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003185 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303187
3188 if (in == NULL) {
3189 ALOGE("%s: stream_in ptr is NULL", __func__);
3190 return -EINVAL;
3191 }
3192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003194 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003195 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196
Mingming Yin2664a5b2015-09-03 10:53:11 -07003197 if (get_usecase_from_list(adev, usecase) == NULL)
3198 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303199 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3200 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003201
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303202 if (CARD_STATUS_OFFLINE == in->card_status||
3203 CARD_STATUS_OFFLINE == adev->card_status) {
3204 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303205 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303206 goto error_config;
3207 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303208
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003209 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303210 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303211 ALOGE("%s: SCO profile is not ready, return error", __func__);
3212 ret = -EIO;
3213 goto error_config;
3214 }
3215 }
3216
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003217 /* Check if source matches incall recording usecase criteria */
3218 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3219 if (ret)
3220 goto error_config;
3221 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003222 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3223
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303224 if (audio_extn_cin_attached_usecase(in))
3225 audio_extn_cin_acquire_usecase(in);
3226
Mingming Yin2664a5b2015-09-03 10:53:11 -07003227 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3228 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3229 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003230 ret = -EINVAL;
3231 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003232 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003233
Eric Laurentb23d5282013-05-14 15:27:20 -07003234 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 if (in->pcm_device_id < 0) {
3236 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3237 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003238 ret = -EINVAL;
3239 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003243
3244 if (!uc_info) {
3245 ret = -ENOMEM;
3246 goto error_config;
3247 }
3248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 uc_info->id = in->usecase;
3250 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003251 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003252 list_init(&uc_info->device_list);
3253 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003254 uc_info->in_snd_device = SND_DEVICE_NONE;
3255 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003257 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003258 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303259 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3260 adev->perf_lock_opts,
3261 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003262 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263
Derek Chenea197282019-01-07 17:35:01 -08003264 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3265 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003266
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303267 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3268
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303269 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303270 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303271 if (ret)
3272 goto error_open;
3273 else
3274 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003275 }
3276
Haynes Mathew George16081042017-05-31 17:16:49 -07003277 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003278 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003279 ALOGE("%s: pcm stream not ready", __func__);
3280 goto error_open;
3281 }
3282 ret = pcm_start(in->pcm);
3283 if (ret < 0) {
3284 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3285 goto error_open;
3286 }
3287 } else {
3288 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3289 unsigned int pcm_open_retry_count = 0;
3290
Zhou Song62ea0282020-03-22 19:53:01 +08003291 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3292 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003293 flags |= PCM_MMAP | PCM_NOIRQ;
3294 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3295 } else if (in->realtime) {
3296 flags |= PCM_MMAP | PCM_NOIRQ;
3297 }
3298
Garmond Leunge2433c32017-09-28 21:51:22 -07003299 if (audio_extn_ffv_get_stream() == in) {
3300 ALOGD("%s: ffv stream, update pcm config", __func__);
3301 audio_extn_ffv_update_pcm_config(&config);
3302 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003303 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3304 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3305
3306 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003307 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003308 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003309 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003310 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303311 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303312 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3313 adev->card_status = CARD_STATUS_OFFLINE;
3314 in->card_status = CARD_STATUS_OFFLINE;
3315 ret = -EIO;
3316 goto error_open;
3317 }
3318
Haynes Mathew George16081042017-05-31 17:16:49 -07003319 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3320 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3321 if (in->pcm != NULL) {
3322 pcm_close(in->pcm);
3323 in->pcm = NULL;
3324 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003325 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003326 ret = -EIO;
3327 goto error_open;
3328 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003329 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003330 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3331 continue;
3332 }
3333 break;
3334 }
3335
3336 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003337 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003338 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003339 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003340 if (ret < 0) {
3341 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3342 pcm_close(in->pcm);
3343 in->pcm = NULL;
3344 goto error_open;
3345 }
3346 register_in_stream(in);
3347 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003348 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003349 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003350 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003351 if (ret < 0) {
3352 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003353 pcm_close(in->pcm);
3354 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003355 goto error_open;
3356 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003357 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003358 }
3359
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003360 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003361 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3362 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003363
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003364 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303365 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3366
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303367done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003368 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303369 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303370 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303371 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003372 return ret;
3373
3374error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003375 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303376 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003378
Eric Laurentc8400632013-02-14 19:04:54 -08003379error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003380 if (audio_extn_cin_attached_usecase(in))
3381 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303382 /*
3383 * sleep 50ms to allow sufficient time for kernel
3384 * drivers to recover incases like SSR.
3385 */
3386 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003387 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303388 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003389 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390}
3391
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003392void lock_input_stream(struct stream_in *in)
3393{
3394 pthread_mutex_lock(&in->pre_lock);
3395 pthread_mutex_lock(&in->lock);
3396 pthread_mutex_unlock(&in->pre_lock);
3397}
3398
3399void lock_output_stream(struct stream_out *out)
3400{
3401 pthread_mutex_lock(&out->pre_lock);
3402 pthread_mutex_lock(&out->lock);
3403 pthread_mutex_unlock(&out->pre_lock);
3404}
3405
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003406/* must be called with out->lock locked */
3407static int send_offload_cmd_l(struct stream_out* out, int command)
3408{
3409 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3410
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003411 if (!cmd) {
3412 ALOGE("failed to allocate mem for command 0x%x", command);
3413 return -ENOMEM;
3414 }
3415
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 ALOGVV("%s %d", __func__, command);
3417
3418 cmd->cmd = command;
3419 list_add_tail(&out->offload_cmd_list, &cmd->node);
3420 pthread_cond_signal(&out->offload_cond);
3421 return 0;
3422}
3423
Gautam Manam14c198b2020-12-24 14:08:04 +05303424/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425static void stop_compressed_output_l(struct stream_out *out)
3426{
Gautam Manam14c198b2020-12-24 14:08:04 +05303427 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003428 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303429 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003430
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003432 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 if (out->compr != NULL) {
3434 compress_stop(out->compr);
3435 while (out->offload_thread_blocked) {
3436 pthread_cond_wait(&out->cond, &out->lock);
3437 }
3438 }
3439}
3440
Varun Balaraje49253e2017-07-06 19:48:56 +05303441bool is_interactive_usecase(audio_usecase_t uc_id)
3442{
3443 unsigned int i;
3444 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3445 if (uc_id == interactive_usecases[i])
3446 return true;
3447 }
3448 return false;
3449}
3450
3451static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3452{
3453 audio_usecase_t ret_uc = USECASE_INVALID;
3454 unsigned int intract_uc_index;
3455 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3456
3457 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3458 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3459 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3460 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3461 ret_uc = interactive_usecases[intract_uc_index];
3462 break;
3463 }
3464 }
3465
3466 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3467 return ret_uc;
3468}
3469
3470static void free_interactive_usecase(struct audio_device *adev,
3471 audio_usecase_t uc_id)
3472{
3473 unsigned int interact_uc_index;
3474 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3475
3476 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3477 if (interactive_usecases[interact_uc_index] == uc_id) {
3478 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3479 break;
3480 }
3481 }
3482 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3483}
3484
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003485bool is_offload_usecase(audio_usecase_t uc_id)
3486{
3487 unsigned int i;
3488 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3489 if (uc_id == offload_usecases[i])
3490 return true;
3491 }
3492 return false;
3493}
3494
Dhananjay Kumarac341582017-02-23 23:42:25 +05303495static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003496{
vivek mehta446c3962015-09-14 10:57:35 -07003497 audio_usecase_t ret_uc = USECASE_INVALID;
3498 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003499 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003500 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303501 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003502 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3503 else
3504 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003505
vivek mehta446c3962015-09-14 10:57:35 -07003506 pthread_mutex_lock(&adev->lock);
3507 if (get_usecase_from_list(adev, ret_uc) != NULL)
3508 ret_uc = USECASE_INVALID;
3509 pthread_mutex_unlock(&adev->lock);
3510
3511 return ret_uc;
3512 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003513
3514 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003515 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3516 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3517 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3518 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003519 break;
3520 }
3521 }
vivek mehta446c3962015-09-14 10:57:35 -07003522
3523 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3524 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003525}
3526
3527static void free_offload_usecase(struct audio_device *adev,
3528 audio_usecase_t uc_id)
3529{
vivek mehta446c3962015-09-14 10:57:35 -07003530 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003531 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003532
3533 if (!adev->multi_offload_enable)
3534 return;
3535
3536 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3537 if (offload_usecases[offload_uc_index] == uc_id) {
3538 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003539 break;
3540 }
3541 }
3542 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3543}
3544
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003545static void *offload_thread_loop(void *context)
3546{
3547 struct stream_out *out = (struct stream_out *) context;
3548 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003549 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003552 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3554
3555 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003556 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003557 out->offload_state = OFFLOAD_STATE_IDLE;
3558 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003559 for (;;) {
3560 struct offload_cmd *cmd = NULL;
3561 stream_callback_event_t event;
3562 bool send_callback = false;
3563
3564 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3565 __func__, list_empty(&out->offload_cmd_list),
3566 out->offload_state);
3567 if (list_empty(&out->offload_cmd_list)) {
3568 ALOGV("%s SLEEPING", __func__);
3569 pthread_cond_wait(&out->offload_cond, &out->lock);
3570 ALOGV("%s RUNNING", __func__);
3571 continue;
3572 }
3573
3574 item = list_head(&out->offload_cmd_list);
3575 cmd = node_to_item(item, struct offload_cmd, node);
3576 list_remove(item);
3577
3578 ALOGVV("%s STATE %d CMD %d out->compr %p",
3579 __func__, out->offload_state, cmd->cmd, out->compr);
3580
3581 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3582 free(cmd);
3583 break;
3584 }
3585
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003586 // allow OFFLOAD_CMD_ERROR reporting during standby
3587 // this is needed to handle failures during compress_open
3588 // Note however that on a pause timeout, the stream is closed
3589 // and no offload usecase will be active. Therefore this
3590 // special case is needed for compress_open failures alone
3591 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3592 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003594 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003595 pthread_cond_signal(&out->cond);
3596 continue;
3597 }
3598 out->offload_thread_blocked = true;
3599 pthread_mutex_unlock(&out->lock);
3600 send_callback = false;
3601 switch(cmd->cmd) {
3602 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003603 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003604 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003605 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003606 send_callback = true;
3607 event = STREAM_CBK_EVENT_WRITE_READY;
3608 break;
3609 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003610 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303611 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003612 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303613 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003614 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303615 if (ret < 0)
3616 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303617 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303618 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003619 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003620 else
3621 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003622 if (-ENETRESET != ret && !(-EINTR == ret &&
3623 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303624 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303625 pthread_mutex_lock(&out->lock);
3626 out->send_new_metadata = 1;
3627 out->send_next_track_params = true;
3628 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303629 event = STREAM_CBK_EVENT_DRAIN_READY;
3630 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3631 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303632 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633 break;
3634 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003635 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003636 ret = compress_drain(out->compr);
3637 ALOGD("copl(%p):out of compress_drain", out);
3638 // EINTR check avoids drain interruption due to SSR
3639 if (-ENETRESET != ret && !(-EINTR == ret &&
3640 CARD_STATUS_OFFLINE == out->card_status)) {
3641 send_callback = true;
3642 event = STREAM_CBK_EVENT_DRAIN_READY;
3643 } else
3644 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303646 case OFFLOAD_CMD_ERROR:
3647 ALOGD("copl(%p): sending error callback to AF", out);
3648 send_callback = true;
3649 event = STREAM_CBK_EVENT_ERROR;
3650 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651 default:
3652 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3653 break;
3654 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003655 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003656 out->offload_thread_blocked = false;
3657 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003658 if (send_callback && out->client_callback) {
3659 ALOGVV("%s: sending client_callback event %d", __func__, event);
3660 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003661 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 free(cmd);
3663 }
3664
3665 pthread_cond_signal(&out->cond);
3666 while (!list_empty(&out->offload_cmd_list)) {
3667 item = list_head(&out->offload_cmd_list);
3668 list_remove(item);
3669 free(node_to_item(item, struct offload_cmd, node));
3670 }
3671 pthread_mutex_unlock(&out->lock);
3672
3673 return NULL;
3674}
3675
3676static int create_offload_callback_thread(struct stream_out *out)
3677{
3678 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3679 list_init(&out->offload_cmd_list);
3680 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3681 offload_thread_loop, out);
3682 return 0;
3683}
3684
3685static int destroy_offload_callback_thread(struct stream_out *out)
3686{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003687 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688 stop_compressed_output_l(out);
3689 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3690
3691 pthread_mutex_unlock(&out->lock);
3692 pthread_join(out->offload_thread, (void **) NULL);
3693 pthread_cond_destroy(&out->offload_cond);
3694
3695 return 0;
3696}
3697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698static int stop_output_stream(struct stream_out *out)
3699{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 struct audio_usecase *uc_info;
3702 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003703 bool has_voip_usecase =
3704 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705
Eric Laurent994a6932013-07-17 11:51:42 -07003706 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003707 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 uc_info = get_usecase_from_list(adev, out->usecase);
3709 if (uc_info == NULL) {
3710 ALOGE("%s: Could not find the usecase (%d) in the list",
3711 __func__, out->usecase);
3712 return -EINVAL;
3713 }
3714
Zhou Songbaddf9f2020-11-20 13:57:39 +08003715 out->a2dp_muted = false;
3716
Derek Chenea197282019-01-07 17:35:01 -08003717 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3718 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003719
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003720 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303721 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003722 if (adev->visualizer_stop_output != NULL)
3723 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003724
3725 audio_extn_dts_remove_state_notifier_node(out->usecase);
3726
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003727 if (adev->offload_effects_stop_output != NULL)
3728 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003729 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3730 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3731 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003732 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003733
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003734 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3735 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003736 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003737 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003738
Eric Laurent150dbfe2013-02-27 14:31:02 -08003739 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003740 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003741
3742 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003743 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003744 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3745 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746
Aalique Grahame22e49102018-12-18 14:23:57 -08003747 audio_extn_extspk_update(adev->extspk);
3748
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003749 if (is_offload_usecase(out->usecase)) {
3750 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3751 adev->dsp_bit_width_enforce_mode,
3752 false);
3753 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003754 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003755 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3756 false);
3757
3758 if (ret != 0)
3759 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3760 /* default service interval was successfully updated,
3761 reopen USB backend with new service interval */
3762 ret = 0;
3763 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003764
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003765 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303766 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003767 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303768 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003769 ALOGV("Disable passthrough , reset mixer to pcm");
3770 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003771#ifdef AUDIO_GKI_ENABLED
3772 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3773 out->compr_config.codec->reserved[0] = 0;
3774#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003775 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003776#endif
Mingming Yin21854652016-04-13 11:54:02 -07003777 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003778 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3779 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003780
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303781 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003782 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303783 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303784
Manish Dewangan21a850a2017-08-14 12:03:55 +05303785 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003786 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3787 if (ret < 0)
3788 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3789 }
3790
Zhou Song642ec432020-12-23 16:11:10 +08003791 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003792 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003793 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003794 struct listnode *node;
3795 struct audio_usecase *usecase;
3796 list_for_each(node, &adev->usecase_list) {
3797 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003798 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3799 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303800 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003801 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003802 continue;
3803
3804 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3805 __func__, usecase->id, use_case_table[usecase->id],
3806 out->usecase, use_case_table[out->usecase]);
3807 select_devices(adev, usecase->id);
3808 }
3809 }
3810
Garmond Leung5fd0b552018-04-17 11:56:12 -07003811 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003812 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 return ret;
3814}
3815
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003816struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3817 unsigned int flags, unsigned int pcm_open_retry_count,
3818 struct pcm_config *config)
3819{
3820 struct pcm* pcm = NULL;
3821
3822 while (1) {
3823 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3824 if (pcm == NULL || !pcm_is_ready(pcm)) {
3825 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3826 if (pcm != NULL) {
3827 pcm_close(pcm);
3828 pcm = NULL;
3829 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003830 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003831 return NULL;
3832
Weiyin Jiang72197252019-10-09 11:49:32 +08003833 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003834 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3835 continue;
3836 }
3837 break;
3838 }
3839
3840 if (pcm_is_ready(pcm)) {
3841 int ret = pcm_prepare(pcm);
3842 if (ret < 0) {
3843 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3844 pcm_close(pcm);
3845 pcm = NULL;
3846 }
3847 }
3848
3849 return pcm;
3850}
3851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852int start_output_stream(struct stream_out *out)
3853{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 struct audio_usecase *uc_info;
3856 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003857 char mixer_ctl_name[128];
3858 struct mixer_ctl *ctl = NULL;
3859 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303860 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003861 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862
Haynes Mathew George380745d2017-10-04 15:27:45 -07003863 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003864 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3865 ret = -EINVAL;
3866 goto error_config;
3867 }
3868
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003869 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303870 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003871 get_device_types(&out->device_list), is_haptic_usecase);
3872
3873 bool is_speaker_active = compare_device_type(&out->device_list,
3874 AUDIO_DEVICE_OUT_SPEAKER);
3875 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3876 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303877
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303878 if (CARD_STATUS_OFFLINE == out->card_status ||
3879 CARD_STATUS_OFFLINE == adev->card_status) {
3880 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303881 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003882 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303883 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303884
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003885 //Update incall music usecase to reflect correct voice session
3886 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3887 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3888 if (ret != 0) {
3889 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3890 __func__, ret);
3891 goto error_config;
3892 }
3893 }
3894
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003895 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003896 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003897 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303898 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303899 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003900 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303901 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3902 ret = -EAGAIN;
3903 goto error_config;
3904 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303905 }
3906 }
3907 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003908 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303909 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003910 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303911 //combo usecase just by pass a2dp
3912 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003913 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303914 } else {
3915 ALOGE("%s: SCO profile is not ready, return error", __func__);
3916 ret = -EAGAIN;
3917 goto error_config;
3918 }
3919 }
3920 }
3921
Eric Laurentb23d5282013-05-14 15:27:20 -07003922 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 if (out->pcm_device_id < 0) {
3924 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3925 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003926 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003927 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 }
3929
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003930 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003931 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3932 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003933 if (adev->haptic_pcm_device_id < 0) {
3934 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3935 __func__, adev->haptic_pcm_device_id, out->usecase);
3936 ret = -EINVAL;
3937 goto error_config;
3938 }
3939 }
3940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003942
3943 if (!uc_info) {
3944 ret = -ENOMEM;
3945 goto error_config;
3946 }
3947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948 uc_info->id = out->usecase;
3949 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003950 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003951 list_init(&uc_info->device_list);
3952 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003953 uc_info->in_snd_device = SND_DEVICE_NONE;
3954 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003955
3956 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003957 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003958 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3959 /* USB backend is not reopened immediately.
3960 This is eventually done as part of select_devices */
3961 }
3962
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003963 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964
Wei Wangf7ca6c92017-11-21 14:51:20 -08003965 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303966 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3967 adev->perf_lock_opts,
3968 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303969
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003970 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303971 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303972 if (audio_extn_passthru_is_enabled() &&
3973 audio_extn_passthru_is_passthrough_stream(out)) {
3974 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303975 }
3976 }
3977
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003978 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003979 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303980 if (!a2dp_combo) {
3981 check_a2dp_restore_l(adev, out, false);
3982 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003983 struct listnode dev;
3984 list_init(&dev);
3985 assign_devices(&dev, &out->device_list);
3986 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3987 reassign_device_list(&out->device_list,
3988 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003989 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003990 reassign_device_list(&out->device_list,
3991 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303992 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003993 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303994 }
3995 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303996 select_devices(adev, out->usecase);
3997 if (is_a2dp_out_device_type(&out->device_list) &&
3998 !adev->a2dp_started) {
3999 if (is_speaker_active || is_speaker_safe_active) {
4000 struct listnode dev;
4001 list_init(&dev);
4002 assign_devices(&dev, &out->device_list);
4003 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4004 reassign_device_list(&out->device_list,
4005 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4006 else
4007 reassign_device_list(&out->device_list,
4008 AUDIO_DEVICE_OUT_SPEAKER, "");
4009 select_devices(adev, out->usecase);
4010 assign_devices(&out->device_list, &dev);
4011 } else {
4012 ret = -EINVAL;
4013 goto error_open;
4014 }
4015 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304016 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004017
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004018 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4019 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004020 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004021 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004022
Derek Chenea197282019-01-07 17:35:01 -08004023 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4024 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004025
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004026 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4027 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004028
4029 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004030 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004031 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4032 ALOGE("%s: pcm stream not ready", __func__);
4033 goto error_open;
4034 }
4035 ret = pcm_start(out->pcm);
4036 if (ret < 0) {
4037 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4038 goto error_open;
4039 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004040 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004041 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004042 unsigned int flags = PCM_OUT;
4043 unsigned int pcm_open_retry_count = 0;
4044 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4045 flags |= PCM_MMAP | PCM_NOIRQ;
4046 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004047 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004048 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004049 } else
4050 flags |= PCM_MONOTONIC;
4051
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004052 if ((adev->vr_audio_mode_enabled) &&
4053 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4054 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4055 "PCM_Dev %d Topology", out->pcm_device_id);
4056 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4057 if (!ctl) {
4058 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4059 __func__, mixer_ctl_name);
4060 } else {
4061 //if success use ULLPP
4062 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4063 __func__, mixer_ctl_name, out->pcm_device_id);
4064 //There is a still a possibility that some sessions
4065 // that request for FAST|RAW when 3D audio is active
4066 //can go through ULLPP. Ideally we expects apps to
4067 //listen to audio focus and stop concurrent playback
4068 //Also, we will look for mode flag (voice_in_communication)
4069 //before enabling the realtime flag.
4070 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4071 }
4072 }
4073
Surendar Karka91fa3682018-07-02 18:12:12 +05304074 if (out->realtime)
4075 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004076 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304077
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004078 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4079 flags, pcm_open_retry_count,
4080 &(out->config));
4081 if (out->pcm == NULL) {
4082 ret = -EIO;
4083 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004085
4086 if (is_haptic_usecase) {
4087 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4088 adev->haptic_pcm_device_id,
4089 flags, pcm_open_retry_count,
4090 &(adev->haptics_config));
4091 // failure to open haptics pcm shouldnt stop audio,
4092 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004093
4094 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4095 ALOGD("%s: enable haptic audio synchronization", __func__);
4096 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4097 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004098 }
4099
Surendar Karka91fa3682018-07-02 18:12:12 +05304100 if (!out->realtime)
4101 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004102 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004103
Zhou Song2b8f28f2017-09-11 10:51:38 +08004104 // apply volume for voip playback after path is set up
4105 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4106 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304107 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4108 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304109 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4110 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004111 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4112 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304113 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004114 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004115 /*
4116 * set custom channel map if:
4117 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4118 * 2. custom channel map has been set by client
4119 * else default channel map of FC/FR/FL can always be set to DSP
4120 */
4121 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4122 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004123 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004124 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4125 adev->dsp_bit_width_enforce_mode,
4126 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004128 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004129 out->compr = compress_open(adev->snd_card,
4130 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004131 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004132 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304133 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304134 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4135 adev->card_status = CARD_STATUS_OFFLINE;
4136 out->card_status = CARD_STATUS_OFFLINE;
4137 ret = -EIO;
4138 goto error_open;
4139 }
4140
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004141 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004142 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004143 compress_close(out->compr);
4144 out->compr = NULL;
4145 ret = -EIO;
4146 goto error_open;
4147 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304148 /* compress_open sends params of the track, so reset the flag here */
4149 out->is_compr_metadata_avail = false;
4150
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004151 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004152 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004153
Fred Oh3f43e742015-03-04 18:42:34 -08004154 /* Since small bufs uses blocking writes, a write will be blocked
4155 for the default max poll time (20s) in the event of an SSR.
4156 Reduce the poll time to observe and deal with SSR faster.
4157 */
Ashish Jain5106d362016-05-11 19:23:33 +05304158 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004159 compress_set_max_poll_wait(out->compr, 1000);
4160 }
4161
Manish Dewangan69426c82017-01-30 17:35:36 +05304162 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304163 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304164
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004165 audio_extn_dts_create_state_notifier_node(out->usecase);
4166 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4167 popcount(out->channel_mask),
4168 out->playback_started);
4169
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004170#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304171 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004172 audio_extn_dolby_send_ddp_endp_params(adev);
4173#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304174 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4175 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004176 if (adev->visualizer_start_output != NULL)
4177 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4178 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304179 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004180 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004181 }
Derek Chenf13dd492018-11-13 14:53:51 -08004182
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004183 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004184 /* Update cached volume from media to offload/direct stream */
4185 struct listnode *node = NULL;
4186 list_for_each(node, &adev->active_outputs_list) {
4187 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4188 streams_output_ctxt_t,
4189 list);
4190 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4191 out->volume_l = out_ctxt->output->volume_l;
4192 out->volume_r = out_ctxt->output->volume_r;
4193 }
4194 }
4195 out_set_compr_volume(&out->stream,
4196 out->volume_l, out->volume_r);
4197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004199
4200 if (ret == 0) {
4201 register_out_stream(out);
4202 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004203 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4204 ALOGE("%s: pcm stream not ready", __func__);
4205 goto error_open;
4206 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004207 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004208 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004209 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004210 if (ret < 0)
4211 goto error_open;
4212 }
4213 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004214 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304215 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304216 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004217
vivek mehtad15d2bf2019-05-17 13:35:10 -07004218 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4219 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4220 audio_low_latency_hint_start();
4221 }
4222
Manish Dewangan21a850a2017-08-14 12:03:55 +05304223 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004224 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004225 if (ret < 0)
4226 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4227 }
4228
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004229 // consider a scenario where on pause lower layers are tear down.
4230 // so on resume, swap mixer control need to be sent only when
4231 // backend is active, hence rather than sending from enable device
4232 // sending it from start of streamtream
4233
4234 platform_set_swap_channels(adev, true);
4235
Haynes Mathew George380745d2017-10-04 15:27:45 -07004236 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304237 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004238 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004239error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004240 if (adev->haptic_pcm) {
4241 pcm_close(adev->haptic_pcm);
4242 adev->haptic_pcm = NULL;
4243 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004244 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304245 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004247error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304248 /*
4249 * sleep 50ms to allow sufficient time for kernel
4250 * drivers to recover incases like SSR.
4251 */
4252 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004253error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004254 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304255 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004256 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257}
4258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259static int check_input_parameters(uint32_t sample_rate,
4260 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004261 int channel_count,
4262 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004264 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304266 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4267 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4268 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004269 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004270 !audio_extn_compr_cap_format_supported(format) &&
4271 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004272 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004273
Aalique Grahame22e49102018-12-18 14:23:57 -08004274 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4275 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4276 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4277 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4278 return -EINVAL;
4279 }
4280
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004281 switch (channel_count) {
4282 case 1:
4283 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304284 case 3:
4285 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004286 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004287 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304288 case 10:
4289 case 12:
4290 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004291 break;
4292 default:
4293 ret = -EINVAL;
4294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295
4296 switch (sample_rate) {
4297 case 8000:
4298 case 11025:
4299 case 12000:
4300 case 16000:
4301 case 22050:
4302 case 24000:
4303 case 32000:
4304 case 44100:
4305 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004306 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304307 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004308 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304309 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 break;
4311 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004312 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 }
4314
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004315 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316}
4317
Naresh Tanniru04f71882018-06-26 17:46:22 +05304318
4319/** Add a value in a list if not already present.
4320 * @return true if value was successfully inserted or already present,
4321 * false if the list is full and does not contain the value.
4322 */
4323static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4324 for (size_t i = 0; i < list_length; i++) {
4325 if (list[i] == value) return true; // value is already present
4326 if (list[i] == 0) { // no values in this slot
4327 list[i] = value;
4328 return true; // value inserted
4329 }
4330 }
4331 return false; // could not insert value
4332}
4333
4334/** Add channel_mask in supported_channel_masks if not already present.
4335 * @return true if channel_mask was successfully inserted or already present,
4336 * false if supported_channel_masks is full and does not contain channel_mask.
4337 */
4338static void register_channel_mask(audio_channel_mask_t channel_mask,
4339 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4340 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4341 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4342}
4343
4344/** Add format in supported_formats if not already present.
4345 * @return true if format was successfully inserted or already present,
4346 * false if supported_formats is full and does not contain format.
4347 */
4348static void register_format(audio_format_t format,
4349 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4350 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4351 "%s: stream can not declare supporting its format %x", __func__, format);
4352}
4353/** Add sample_rate in supported_sample_rates if not already present.
4354 * @return true if sample_rate was successfully inserted or already present,
4355 * false if supported_sample_rates is full and does not contain sample_rate.
4356 */
4357static void register_sample_rate(uint32_t sample_rate,
4358 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4359 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4360 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4361}
4362
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004363static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4364{
4365 uint32_t high = num1, low = num2, temp = 0;
4366
4367 if (!num1 || !num2)
4368 return 0;
4369
4370 if (num1 < num2) {
4371 high = num2;
4372 low = num1;
4373 }
4374
4375 while (low != 0) {
4376 temp = low;
4377 low = high % low;
4378 high = temp;
4379 }
4380 return (num1 * num2)/high;
4381}
4382
4383static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4384{
4385 uint32_t remainder = 0;
4386
4387 if (!multiplier)
4388 return num;
4389
4390 remainder = num % multiplier;
4391 if (remainder)
4392 num += (multiplier - remainder);
4393
4394 return num;
4395}
4396
Aalique Grahame22e49102018-12-18 14:23:57 -08004397static size_t get_stream_buffer_size(size_t duration_ms,
4398 uint32_t sample_rate,
4399 audio_format_t format,
4400 int channel_count,
4401 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402{
4403 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004404 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405
Aalique Grahame22e49102018-12-18 14:23:57 -08004406 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004407 if (is_low_latency)
4408 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304409
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004410 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004411 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412
Ralf Herzbd08d632018-09-28 15:50:49 +02004413 /* make sure the size is multiple of 32 bytes and additionally multiple of
4414 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004415 * At 48 kHz mono 16-bit PCM:
4416 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4417 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004418 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004419 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004420 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004421
4422 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423}
4424
Aalique Grahame22e49102018-12-18 14:23:57 -08004425static size_t get_input_buffer_size(uint32_t sample_rate,
4426 audio_format_t format,
4427 int channel_count,
4428 bool is_low_latency)
4429{
4430 /* Don't know if USB HIFI in this context so use true to be conservative */
4431 if (check_input_parameters(sample_rate, format, channel_count,
4432 true /*is_usb_hifi */) != 0)
4433 return 0;
4434
4435 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4436 sample_rate,
4437 format,
4438 channel_count,
4439 is_low_latency);
4440}
4441
Derek Chenf6318be2017-06-12 17:16:24 -04004442size_t get_output_period_size(uint32_t sample_rate,
4443 audio_format_t format,
4444 int channel_count,
4445 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304446{
4447 size_t size = 0;
4448 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4449
4450 if ((duration == 0) || (sample_rate == 0) ||
4451 (bytes_per_sample == 0) || (channel_count == 0)) {
4452 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4453 bytes_per_sample, channel_count);
4454 return -EINVAL;
4455 }
4456
4457 size = (sample_rate *
4458 duration *
4459 bytes_per_sample *
4460 channel_count) / 1000;
4461 /*
4462 * To have same PCM samples for all channels, the buffer size requires to
4463 * be multiple of (number of channels * bytes per sample)
4464 * For writes to succeed, the buffer must be written at address which is multiple of 32
4465 */
4466 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4467
4468 return (size/(channel_count * bytes_per_sample));
4469}
4470
Zhou Song48453a02018-01-10 17:50:59 +08004471static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304472{
4473 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004474 uint64_t written_frames = 0;
4475 uint64_t kernel_frames = 0;
4476 uint64_t dsp_frames = 0;
4477 uint64_t signed_frames = 0;
4478 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304479
4480 /* This adjustment accounts for buffering after app processor.
4481 * It is based on estimated DSP latency per use case, rather than exact.
4482 */
George Gao9ba8a142020-07-23 14:30:03 -07004483 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004484 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304485
Zhou Song48453a02018-01-10 17:50:59 +08004486 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004487 written_frames = out->written /
4488 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4489
Ashish Jain5106d362016-05-11 19:23:33 +05304490 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4491 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4492 * hence only estimate.
4493 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004494 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4495 kernel_frames = kernel_buffer_size /
4496 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304497
Weiyin Jiang4813da12020-05-28 00:37:28 +08004498 if (written_frames >= (kernel_frames + dsp_frames))
4499 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304500
Zhou Song48453a02018-01-10 17:50:59 +08004501 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304502 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004503 if (timestamp != NULL )
4504 *timestamp = out->writeAt;
4505 } else if (timestamp != NULL) {
4506 clock_gettime(CLOCK_MONOTONIC, timestamp);
4507 }
4508 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304509
Weiyin Jiang4813da12020-05-28 00:37:28 +08004510 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4511 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304512
4513 return actual_frames_rendered;
4514}
4515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4517{
4518 struct stream_out *out = (struct stream_out *)stream;
4519
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004520 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521}
4522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004523static int out_set_sample_rate(struct audio_stream *stream __unused,
4524 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525{
4526 return -ENOSYS;
4527}
4528
4529static size_t out_get_buffer_size(const struct audio_stream *stream)
4530{
4531 struct stream_out *out = (struct stream_out *)stream;
4532
Varun Balaraje49253e2017-07-06 19:48:56 +05304533 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304534 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304535 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304536 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4537 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4538 else
4539 return out->compr_config.fragment_size;
4540 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004541 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304542 else if (is_offload_usecase(out->usecase) &&
4543 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304544 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004545
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004546 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004547 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548}
4549
4550static uint32_t out_get_channels(const struct audio_stream *stream)
4551{
4552 struct stream_out *out = (struct stream_out *)stream;
4553
4554 return out->channel_mask;
4555}
4556
4557static audio_format_t out_get_format(const struct audio_stream *stream)
4558{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004559 struct stream_out *out = (struct stream_out *)stream;
4560
4561 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562}
4563
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004564static int out_set_format(struct audio_stream *stream __unused,
4565 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566{
4567 return -ENOSYS;
4568}
4569
4570static int out_standby(struct audio_stream *stream)
4571{
4572 struct stream_out *out = (struct stream_out *)stream;
4573 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004574 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004575
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304576 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4577 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004579 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004581 if (adev->adm_deregister_stream)
4582 adev->adm_deregister_stream(adev->adm_data, out->handle);
4583
Weiyin Jiang280ea742020-09-08 20:28:22 +08004584 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004585 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004586 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004587
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004588 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004590 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4591 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304592 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004593 pthread_mutex_unlock(&adev->lock);
4594 pthread_mutex_unlock(&out->lock);
4595 ALOGD("VOIP output entered standby");
4596 return 0;
4597 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004598 if (out->pcm) {
4599 pcm_close(out->pcm);
4600 out->pcm = NULL;
4601 }
Meng Wanga09da002020-04-20 12:56:04 +08004602 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4603 if (adev->haptic_pcm) {
4604 pcm_close(adev->haptic_pcm);
4605 adev->haptic_pcm = NULL;
4606 }
4607
4608 if (adev->haptic_buffer != NULL) {
4609 free(adev->haptic_buffer);
4610 adev->haptic_buffer = NULL;
4611 adev->haptic_buffer_size = 0;
4612 }
4613 adev->haptic_pcm_device_id = 0;
4614 }
4615
Haynes Mathew George16081042017-05-31 17:16:49 -07004616 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4617 do_stop = out->playback_started;
4618 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004619
4620 if (out->mmap_shared_memory_fd >= 0) {
4621 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4622 __func__, out->mmap_shared_memory_fd);
4623 close(out->mmap_shared_memory_fd);
4624 out->mmap_shared_memory_fd = -1;
4625 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004626 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004627 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004628 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304629 out->send_next_track_params = false;
4630 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004631 out->gapless_mdata.encoder_delay = 0;
4632 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633 if (out->compr != NULL) {
4634 compress_close(out->compr);
4635 out->compr = NULL;
4636 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004637 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004638 if (do_stop) {
4639 stop_output_stream(out);
4640 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304641 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004642 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004643 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 }
4645 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004646 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 return 0;
4648}
4649
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304650static int out_on_error(struct audio_stream *stream)
4651{
4652 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004653 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304654
4655 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004656 // always send CMD_ERROR for offload streams, this
4657 // is needed e.g. when SSR happens within compress_open
4658 // since the stream is active, offload_callback_thread is also active.
4659 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4660 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004661 }
4662 pthread_mutex_unlock(&out->lock);
4663
4664 status = out_standby(&out->stream.common);
4665
4666 lock_output_stream(out);
4667 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004668 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304669 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304670
4671 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4672 ALOGD("Setting previous card status if offline");
4673 out->prev_card_status_offline = true;
4674 }
4675
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304676 pthread_mutex_unlock(&out->lock);
4677
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004678 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304679}
4680
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304681/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004682 * standby implementation without locks, assumes that the callee already
4683 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304684 */
4685int out_standby_l(struct audio_stream *stream)
4686{
4687 struct stream_out *out = (struct stream_out *)stream;
4688 struct audio_device *adev = out->dev;
4689
4690 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4691 stream, out->usecase, use_case_table[out->usecase]);
4692
4693 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004694 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304695 if (adev->adm_deregister_stream)
4696 adev->adm_deregister_stream(adev->adm_data, out->handle);
4697
Weiyin Jiang280ea742020-09-08 20:28:22 +08004698 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304699 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004700 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304701
4702 out->standby = true;
4703 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4704 voice_extn_compress_voip_close_output_stream(stream);
4705 out->started = 0;
4706 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004707 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304708 return 0;
4709 } else if (!is_offload_usecase(out->usecase)) {
4710 if (out->pcm) {
4711 pcm_close(out->pcm);
4712 out->pcm = NULL;
4713 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004714 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4715 if (adev->haptic_pcm) {
4716 pcm_close(adev->haptic_pcm);
4717 adev->haptic_pcm = NULL;
4718 }
4719
4720 if (adev->haptic_buffer != NULL) {
4721 free(adev->haptic_buffer);
4722 adev->haptic_buffer = NULL;
4723 adev->haptic_buffer_size = 0;
4724 }
4725 adev->haptic_pcm_device_id = 0;
4726 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304727 } else {
4728 ALOGD("copl(%p):standby", out);
4729 out->send_next_track_params = false;
4730 out->is_compr_metadata_avail = false;
4731 out->gapless_mdata.encoder_delay = 0;
4732 out->gapless_mdata.encoder_padding = 0;
4733 if (out->compr != NULL) {
4734 compress_close(out->compr);
4735 out->compr = NULL;
4736 }
4737 }
4738 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004739 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304740 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004741 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304742 return 0;
4743}
4744
Aalique Grahame22e49102018-12-18 14:23:57 -08004745static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746{
Aalique Grahame22e49102018-12-18 14:23:57 -08004747 struct stream_out *out = (struct stream_out *)stream;
4748
4749 // We try to get the lock for consistency,
4750 // but it isn't necessary for these variables.
4751 // If we're not in standby, we may be blocked on a write.
4752 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4753 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4754 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4755
Andy Hunga1f48fa2019-07-01 18:14:53 -07004756 char buffer[256]; // for statistics formatting
4757 if (!is_offload_usecase(out->usecase)) {
4758 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4759 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4760 }
4761
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004762 if (out->start_latency_ms.n > 0) {
4763 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4764 dprintf(fd, " Start latency ms: %s\n", buffer);
4765 }
4766
Aalique Grahame22e49102018-12-18 14:23:57 -08004767 if (locked) {
4768 pthread_mutex_unlock(&out->lock);
4769 }
4770
4771 // dump error info
4772 (void)error_log_dump(
4773 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775 return 0;
4776}
4777
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004778static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4779{
4780 int ret = 0;
4781 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004782
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004783 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004784 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004785 return -EINVAL;
4786 }
4787
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304788 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004789
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004790 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4791 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304792 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004793 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004794 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4795 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304796 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004797 }
4798
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004799 ALOGV("%s new encoder delay %u and padding %u", __func__,
4800 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4801
4802 return 0;
4803}
4804
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004805static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4806{
4807 return out == adev->primary_output || out == adev->voice_tx_output;
4808}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004809
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304810// note: this call is safe only if the stream_cb is
4811// removed first in close_output_stream (as is done now).
4812static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4813{
4814 if (!stream || !parms)
4815 return;
4816
4817 struct stream_out *out = (struct stream_out *)stream;
4818 struct audio_device *adev = out->dev;
4819
4820 card_status_t status;
4821 int card;
4822 if (parse_snd_card_status(parms, &card, &status) < 0)
4823 return;
4824
4825 pthread_mutex_lock(&adev->lock);
4826 bool valid_cb = (card == adev->snd_card);
4827 pthread_mutex_unlock(&adev->lock);
4828
4829 if (!valid_cb)
4830 return;
4831
4832 lock_output_stream(out);
4833 if (out->card_status != status)
4834 out->card_status = status;
4835 pthread_mutex_unlock(&out->lock);
4836
4837 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4838 use_case_table[out->usecase],
4839 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4840
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304841 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304842 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304843 if (voice_is_call_state_active(adev) &&
4844 out == adev->primary_output) {
4845 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4846 pthread_mutex_lock(&adev->lock);
4847 voice_stop_call(adev);
4848 adev->mode = AUDIO_MODE_NORMAL;
4849 pthread_mutex_unlock(&adev->lock);
4850 }
4851 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304852 return;
4853}
4854
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004855int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004856 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857{
4858 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004859 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004860 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004861 bool bypass_a2dp = false;
4862 bool reconfig = false;
4863 unsigned long service_interval = 0;
4864
4865 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4867
4868 list_init(&new_devices);
4869 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870
4871 lock_output_stream(out);
4872 pthread_mutex_lock(&adev->lock);
4873
4874 /*
4875 * When HDMI cable is unplugged the music playback is paused and
4876 * the policy manager sends routing=0. But the audioflinger continues
4877 * to write data until standby time (3sec). As the HDMI core is
4878 * turned off, the write gets blocked.
4879 * Avoid this by routing audio to speaker until standby.
4880 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004881 if (is_single_device_type_equal(&out->device_list,
4882 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004883 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004884 !audio_extn_passthru_is_passthrough_stream(out) &&
4885 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004886 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 }
4888 /*
4889 * When A2DP is disconnected the
4890 * music playback is paused and the policy manager sends routing=0
4891 * But the audioflinger continues to write data until standby time
4892 * (3sec). As BT is turned off, the write gets blocked.
4893 * Avoid this by routing audio to speaker until standby.
4894 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004895 if (is_a2dp_out_device_type(&out->device_list) &&
4896 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004897 !audio_extn_a2dp_source_is_ready() &&
4898 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004899 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004900 }
4901 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08004902 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004903 * and the policy manager send routing=0. But if the USB is connected
4904 * back before the standby time, AFE is not closed and opened
4905 * when USB is connected back. So routing to speker will guarantee
4906 * AFE reconfiguration and AFE will be opend once USB is connected again
4907 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004908 if (is_usb_out_device_type(&out->device_list) &&
4909 list_empty(&new_devices) &&
4910 !audio_extn_usb_connected(NULL)) {
4911 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4912 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004913 /* To avoid a2dp to sco overlapping / BT device improper state
4914 * check with BT lib about a2dp streaming support before routing
4915 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004916 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004917 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004918 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4919 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004920 //combo usecase just by pass a2dp
4921 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4922 bypass_a2dp = true;
4923 } else {
4924 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4925 /* update device to a2dp and don't route as BT returned error
4926 * However it is still possible a2dp routing called because
4927 * of current active device disconnection (like wired headset)
4928 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004929 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004930 pthread_mutex_unlock(&adev->lock);
4931 pthread_mutex_unlock(&out->lock);
4932 goto error;
4933 }
4934 }
4935 }
4936
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004937 // Workaround: If routing to an non existing usb device, fail gracefully
4938 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004939 if (is_usb_out_device_type(&new_devices)) {
4940 struct str_parms *parms =
4941 str_parms_create_str(get_usb_device_address(&new_devices));
4942 if (!parms)
4943 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08004944 if (!audio_extn_usb_connected(NULL)) {
4945 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004946 pthread_mutex_unlock(&adev->lock);
4947 pthread_mutex_unlock(&out->lock);
4948 str_parms_destroy(parms);
4949 ret = -ENOSYS;
4950 goto error;
4951 }
4952 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004953 }
4954
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004955 // Workaround: If routing to an non existing hdmi device, fail gracefully
4956 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4957 (platform_get_edid_info_v2(adev->platform,
4958 out->extconn.cs.controller,
4959 out->extconn.cs.stream) != 0)) {
4960 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4961 pthread_mutex_unlock(&adev->lock);
4962 pthread_mutex_unlock(&out->lock);
4963 ret = -ENOSYS;
4964 goto error;
4965 }
4966
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004967 /*
4968 * select_devices() call below switches all the usecases on the same
4969 * backend to the new device. Refer to check_usecases_codec_backend() in
4970 * the select_devices(). But how do we undo this?
4971 *
4972 * For example, music playback is active on headset (deep-buffer usecase)
4973 * and if we go to ringtones and select a ringtone, low-latency usecase
4974 * will be started on headset+speaker. As we can't enable headset+speaker
4975 * and headset devices at the same time, select_devices() switches the music
4976 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4977 * So when the ringtone playback is completed, how do we undo the same?
4978 *
4979 * We are relying on the out_set_parameters() call on deep-buffer output,
4980 * once the ringtone playback is ended.
4981 * NOTE: We should not check if the current devices are same as new devices.
4982 * Because select_devices() must be called to switch back the music
4983 * playback to headset.
4984 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004985 if (!list_empty(&new_devices)) {
4986 bool same_dev = compare_devices(&out->device_list, &new_devices);
4987 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004988
4989 if (output_drives_call(adev, out)) {
4990 if (!voice_is_call_state_active(adev)) {
4991 if (adev->mode == AUDIO_MODE_IN_CALL) {
4992 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004993 ret = voice_start_call(adev);
4994 }
4995 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08004996 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004997 adev->current_call_output = out;
4998 voice_update_devices_for_all_voice_usecases(adev);
4999 }
5000 }
5001
Mingshu Pang971ff702020-09-09 15:28:22 +08005002 if (is_usb_out_device_type(&out->device_list)) {
5003 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5004 audio_extn_usb_set_service_interval(true /*playback*/,
5005 service_interval,
5006 &reconfig);
5007 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5008 }
5009
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005010 if (!out->standby) {
5011 if (!same_dev) {
5012 ALOGV("update routing change");
5013 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5014 adev->perf_lock_opts,
5015 adev->perf_lock_opts_size);
5016 if (adev->adm_on_routing_change)
5017 adev->adm_on_routing_change(adev->adm_data,
5018 out->handle);
5019 }
5020 if (!bypass_a2dp) {
5021 select_devices(adev, out->usecase);
5022 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005023 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5024 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005025 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005026 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005027 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005028 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005029 }
5030
5031 if (!same_dev) {
5032 // on device switch force swap, lower functions will make sure
5033 // to check if swap is allowed or not.
5034 platform_set_swap_channels(adev, true);
5035 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5036 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005037 pthread_mutex_lock(&out->latch_lock);
5038 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5039 if (out->a2dp_muted) {
5040 out->a2dp_muted = false;
5041 if (is_offload_usecase(out->usecase))
5042 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5043 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5044 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005045 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005046 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005047 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5048 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5049 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005050 }
5051 }
5052
5053 pthread_mutex_unlock(&adev->lock);
5054 pthread_mutex_unlock(&out->lock);
5055
5056 /*handles device and call state changes*/
5057 audio_extn_extspk_update(adev->extspk);
5058
5059error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005060 ALOGV("%s: exit: code(%d)", __func__, ret);
5061 return ret;
5062}
5063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5065{
5066 struct stream_out *out = (struct stream_out *)stream;
5067 struct audio_device *adev = out->dev;
5068 struct str_parms *parms;
5069 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005070 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005071 int ext_controller = -1;
5072 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073
sangwoobc677242013-08-08 16:53:43 +09005074 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005075 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005076 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305077 if (!parms)
5078 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005079
5080 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5081 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005082 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005083 out->extconn.cs.controller = ext_controller;
5084 out->extconn.cs.stream = ext_stream;
5085 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5086 use_case_table[out->usecase], out->extconn.cs.controller,
5087 out->extconn.cs.stream);
5088 }
5089
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005090 if (out == adev->primary_output) {
5091 pthread_mutex_lock(&adev->lock);
5092 audio_extn_set_parameters(adev, parms);
5093 pthread_mutex_unlock(&adev->lock);
5094 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005095 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005096 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005097 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005098
5099 audio_extn_dts_create_state_notifier_node(out->usecase);
5100 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5101 popcount(out->channel_mask),
5102 out->playback_started);
5103
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005104 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005105 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005106
Surendar Karkaf51b5842018-04-26 11:28:38 +05305107 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5108 sizeof(value));
5109 if (err >= 0) {
5110 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5111 audio_extn_send_dual_mono_mixing_coefficients(out);
5112 }
5113
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305114 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5115 if (err >= 0) {
5116 strlcpy(out->profile, value, sizeof(out->profile));
5117 ALOGV("updating stream profile with value '%s'", out->profile);
5118 lock_output_stream(out);
5119 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5120 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005121 &out->device_list, out->flags,
5122 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305123 out->sample_rate, out->bit_width,
5124 out->channel_mask, out->profile,
5125 &out->app_type_cfg);
5126 pthread_mutex_unlock(&out->lock);
5127 }
5128
Alexy Joseph98988832017-01-13 14:56:59 -08005129 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005130 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5131 // and vendor.audio.hal.output.suspend.supported is set to true
5132 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005133 //check suspend parameter only for low latency and if the property
5134 //is enabled
5135 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5136 ALOGI("%s: got suspend_playback %s", __func__, value);
5137 lock_output_stream(out);
5138 if (!strncmp(value, "false", 5)) {
5139 //suspend_playback=false is supposed to set QOS value back to 75%
5140 //the mixer control sent with value Enable will achieve that
5141 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5142 } else if (!strncmp (value, "true", 4)) {
5143 //suspend_playback=true is supposed to remove QOS value
5144 //resetting the mixer control will set the default value
5145 //for the mixer control which is Disable and this removes the QOS vote
5146 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5147 } else {
5148 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5149 " got %s", __func__, value);
5150 ret = -1;
5151 }
5152
5153 if (ret != 0) {
5154 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5155 __func__, out->pm_qos_mixer_path, ret);
5156 }
5157
5158 pthread_mutex_unlock(&out->lock);
5159 }
5160 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005161
Alexy Joseph98988832017-01-13 14:56:59 -08005162 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005163 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305164error:
Eric Laurent994a6932013-07-17 11:51:42 -07005165 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166 return ret;
5167}
5168
Paul McLeana50b7332018-12-17 08:24:21 -07005169static int in_set_microphone_direction(const struct audio_stream_in *stream,
5170 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005171 struct stream_in *in = (struct stream_in *)stream;
5172
5173 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5174
5175 in->direction = dir;
5176
5177 if (in->standby)
5178 return 0;
5179
5180 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005181}
5182
5183static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005184 struct stream_in *in = (struct stream_in *)stream;
5185
5186 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5187
5188 if (zoom > 1.0 || zoom < -1.0)
5189 return -EINVAL;
5190
5191 in->zoom = zoom;
5192
5193 if (in->standby)
5194 return 0;
5195
5196 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005197}
5198
5199
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005200static bool stream_get_parameter_channels(struct str_parms *query,
5201 struct str_parms *reply,
5202 audio_channel_mask_t *supported_channel_masks) {
5203 int ret = -1;
5204 char value[512];
5205 bool first = true;
5206 size_t i, j;
5207
5208 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5209 ret = 0;
5210 value[0] = '\0';
5211 i = 0;
5212 while (supported_channel_masks[i] != 0) {
5213 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5214 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5215 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305216 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005217
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305218 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005219 first = false;
5220 break;
5221 }
5222 }
5223 i++;
5224 }
5225 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5226 }
5227 return ret == 0;
5228}
5229
5230static bool stream_get_parameter_formats(struct str_parms *query,
5231 struct str_parms *reply,
5232 audio_format_t *supported_formats) {
5233 int ret = -1;
5234 char value[256];
5235 size_t i, j;
5236 bool first = true;
5237
5238 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5239 ret = 0;
5240 value[0] = '\0';
5241 i = 0;
5242 while (supported_formats[i] != 0) {
5243 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5244 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5245 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305246 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005247 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305248 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005249 first = false;
5250 break;
5251 }
5252 }
5253 i++;
5254 }
5255 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5256 }
5257 return ret == 0;
5258}
5259
5260static bool stream_get_parameter_rates(struct str_parms *query,
5261 struct str_parms *reply,
5262 uint32_t *supported_sample_rates) {
5263
5264 int i;
5265 char value[256];
5266 int ret = -1;
5267 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5268 ret = 0;
5269 value[0] = '\0';
5270 i=0;
5271 int cursor = 0;
5272 while (supported_sample_rates[i]) {
5273 int avail = sizeof(value) - cursor;
5274 ret = snprintf(value + cursor, avail, "%s%d",
5275 cursor > 0 ? "|" : "",
5276 supported_sample_rates[i]);
5277 if (ret < 0 || ret >= avail) {
5278 // if cursor is at the last element of the array
5279 // overwrite with \0 is duplicate work as
5280 // snprintf already put a \0 in place.
5281 // else
5282 // we had space to write the '|' at value[cursor]
5283 // (which will be overwritten) or no space to fill
5284 // the first element (=> cursor == 0)
5285 value[cursor] = '\0';
5286 break;
5287 }
5288 cursor += ret;
5289 ++i;
5290 }
5291 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5292 value);
5293 }
5294 return ret >= 0;
5295}
5296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5298{
5299 struct stream_out *out = (struct stream_out *)stream;
5300 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005301 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 char value[256];
5303 struct str_parms *reply = str_parms_create();
5304 size_t i, j;
5305 int ret;
5306 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005307
5308 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005309 if (reply) {
5310 str_parms_destroy(reply);
5311 }
5312 if (query) {
5313 str_parms_destroy(query);
5314 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005315 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5316 return NULL;
5317 }
5318
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005319 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5321 if (ret >= 0) {
5322 value[0] = '\0';
5323 i = 0;
5324 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005325 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5326 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005327 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005328 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005329 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005330 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331 first = false;
5332 break;
5333 }
5334 }
5335 i++;
5336 }
5337 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5338 str = str_parms_to_str(reply);
5339 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005340 voice_extn_out_get_parameters(out, query, reply);
5341 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005342 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005343
Alexy Joseph62142aa2015-11-16 15:10:34 -08005344
5345 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5346 if (ret >= 0) {
5347 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305348 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5349 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005350 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305351 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005352 } else {
5353 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305354 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005355 }
5356 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005357 if (str)
5358 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005359 str = str_parms_to_str(reply);
5360 }
5361
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005362 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5363 if (ret >= 0) {
5364 value[0] = '\0';
5365 i = 0;
5366 first = true;
5367 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005368 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5369 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005370 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005371 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005372 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005373 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005374 first = false;
5375 break;
5376 }
5377 }
5378 i++;
5379 }
5380 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005381 if (str)
5382 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005383 str = str_parms_to_str(reply);
5384 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005385
5386 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5387 if (ret >= 0) {
5388 value[0] = '\0';
5389 i = 0;
5390 first = true;
5391 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005392 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5393 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005394 if (!first) {
5395 strlcat(value, "|", sizeof(value));
5396 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005397 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005398 first = false;
5399 break;
5400 }
5401 }
5402 i++;
5403 }
5404 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5405 if (str)
5406 free(str);
5407 str = str_parms_to_str(reply);
5408 }
5409
Alexy Joseph98988832017-01-13 14:56:59 -08005410 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5411 //only low latency track supports suspend_resume
5412 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005413 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005414 if (str)
5415 free(str);
5416 str = str_parms_to_str(reply);
5417 }
5418
5419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420 str_parms_destroy(query);
5421 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005422 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005423 return str;
5424}
5425
5426static uint32_t out_get_latency(const struct audio_stream_out *stream)
5427{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005428 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005429 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005430 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431
Alexy Josephaa54c872014-12-03 02:46:47 -08005432 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305433 lock_output_stream(out);
5434 latency = audio_extn_utils_compress_get_dsp_latency(out);
5435 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005436 } else if ((out->realtime) ||
5437 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005438 // since the buffer won't be filled up faster than realtime,
5439 // return a smaller number
5440 if (out->config.rate)
5441 period_ms = (out->af_period_multiplier * out->config.period_size *
5442 1000) / (out->config.rate);
5443 else
5444 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005445 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005446 } else {
5447 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005448 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005449 }
5450
Zhou Songd2537a02020-06-11 22:04:46 +08005451 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005452 latency += audio_extn_a2dp_get_encoder_latency();
5453
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305454 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005455 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456}
5457
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305458static float AmpToDb(float amplification)
5459{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305460 float db = DSD_VOLUME_MIN_DB;
5461 if (amplification > 0) {
5462 db = 20 * log10(amplification);
5463 if(db < DSD_VOLUME_MIN_DB)
5464 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305465 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305466 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305467}
5468
Arun Mirpuri5d170872019-03-26 13:21:31 -07005469static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5470 float right)
5471{
5472 struct stream_out *out = (struct stream_out *)stream;
5473 long volume = 0;
5474 char mixer_ctl_name[128] = "";
5475 struct audio_device *adev = out->dev;
5476 struct mixer_ctl *ctl = NULL;
5477 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5478 PCM_PLAYBACK);
5479
5480 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5481 "Playback %d Volume", pcm_device_id);
5482 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5483 if (!ctl) {
5484 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5485 __func__, mixer_ctl_name);
5486 return -EINVAL;
5487 }
5488 if (left != right)
5489 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5490 __func__, left, right);
5491 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5492 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5493 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5494 __func__, mixer_ctl_name, volume);
5495 return -EINVAL;
5496 }
5497 return 0;
5498}
5499
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305500static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5501 float right)
5502{
5503 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305504 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305505 char mixer_ctl_name[128];
5506 struct audio_device *adev = out->dev;
5507 struct mixer_ctl *ctl;
5508 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5509 PCM_PLAYBACK);
5510
5511 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5512 "Compress Playback %d Volume", pcm_device_id);
5513 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5514 if (!ctl) {
5515 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5516 __func__, mixer_ctl_name);
5517 return -EINVAL;
5518 }
5519 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5520 __func__, mixer_ctl_name, left, right);
5521 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5522 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5523 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5524
5525 return 0;
5526}
5527
Zhou Song2b8f28f2017-09-11 10:51:38 +08005528static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5529 float right)
5530{
5531 struct stream_out *out = (struct stream_out *)stream;
5532 char mixer_ctl_name[] = "App Type Gain";
5533 struct audio_device *adev = out->dev;
5534 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305535 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005536
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005537 if (!is_valid_volume(left, right)) {
5538 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5539 __func__, left, right);
5540 return -EINVAL;
5541 }
5542
Zhou Song2b8f28f2017-09-11 10:51:38 +08005543 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",
5546 __func__, mixer_ctl_name);
5547 return -EINVAL;
5548 }
5549
5550 set_values[0] = 0; //0: Rx Session 1:Tx Session
5551 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305552 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5553 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005554
5555 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5556 return 0;
5557}
5558
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305559static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5560 float right)
5561{
5562 struct stream_out *out = (struct stream_out *)stream;
5563 /* Volume control for pcm playback */
5564 if (left != right) {
5565 return -EINVAL;
5566 } else {
5567 char mixer_ctl_name[128];
5568 struct audio_device *adev = out->dev;
5569 struct mixer_ctl *ctl;
5570 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5571 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5572 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5573 if (!ctl) {
5574 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5575 return -EINVAL;
5576 }
5577
5578 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5579 int ret = mixer_ctl_set_value(ctl, 0, volume);
5580 if (ret < 0) {
5581 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5582 return -EINVAL;
5583 }
5584
5585 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5586
5587 return 0;
5588 }
5589}
5590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591static int out_set_volume(struct audio_stream_out *stream, float left,
5592 float right)
5593{
Eric Laurenta9024de2013-04-04 09:19:12 -07005594 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005595 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305596 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005597
Arun Mirpuri5d170872019-03-26 13:21:31 -07005598 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005599 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5600 /* only take left channel into account: the API is for stereo anyway */
5601 out->muted = (left == 0.0f);
5602 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005603 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305604 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005605 /*
5606 * Set mute or umute on HDMI passthrough stream.
5607 * Only take left channel into account.
5608 * Mute is 0 and unmute 1
5609 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305610 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305611 } else if (out->format == AUDIO_FORMAT_DSD){
5612 char mixer_ctl_name[128] = "DSD Volume";
5613 struct audio_device *adev = out->dev;
5614 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5615
5616 if (!ctl) {
5617 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5618 __func__, mixer_ctl_name);
5619 return -EINVAL;
5620 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305621 volume[0] = (long)(AmpToDb(left));
5622 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305623 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5624 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005625 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005626 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005627 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5628 struct listnode *node = NULL;
5629 list_for_each(node, &adev->active_outputs_list) {
5630 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5631 streams_output_ctxt_t,
5632 list);
5633 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5634 out->volume_l = out_ctxt->output->volume_l;
5635 out->volume_r = out_ctxt->output->volume_r;
5636 }
5637 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005638 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005639 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005640 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5641 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005642 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005643 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005644 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005645 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005646 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5647 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305648 ret = out_set_compr_volume(stream, left, right);
5649 out->volume_l = left;
5650 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005651 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305652 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005653 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005654 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005655 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5656 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005657 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005658 if (!out->standby) {
5659 audio_extn_utils_send_app_type_gain(out->dev,
5660 out->app_type_cfg.app_type,
5661 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005662 if (!out->a2dp_muted)
5663 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005664 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005665 out->volume_l = left;
5666 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005667 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005668 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005669 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5670 ALOGV("%s: MMAP set volume called", __func__);
5671 if (!out->standby)
5672 ret = out_set_mmap_volume(stream, left, right);
5673 out->volume_l = left;
5674 out->volume_r = right;
5675 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305676 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305677 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5678 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005679 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305680 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005681 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305682 ret = out_set_pcm_volume(stream, left, right);
5683 else
5684 out->apply_volume = true;
5685
5686 out->volume_l = left;
5687 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005688 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305689 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005690 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5691 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005692 pthread_mutex_lock(&out->latch_lock);
5693 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005694 ret = out_set_pcm_volume(stream, left, right);
5695 out->volume_l = left;
5696 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005697 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005698 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005699 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701 return -ENOSYS;
5702}
5703
Zhou Songc9672822017-08-16 16:01:39 +08005704static void update_frames_written(struct stream_out *out, size_t bytes)
5705{
5706 size_t bpf = 0;
5707
5708 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5709 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5710 bpf = 1;
5711 else if (!is_offload_usecase(out->usecase))
5712 bpf = audio_bytes_per_sample(out->format) *
5713 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005714
5715 pthread_mutex_lock(&out->position_query_lock);
5716 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005717 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005718 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5719 }
5720 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005721}
5722
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005723int split_and_write_audio_haptic_data(struct stream_out *out,
5724 const void *buffer, size_t bytes_to_write)
5725{
5726 struct audio_device *adev = out->dev;
5727
5728 int ret = 0;
5729 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5730 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5731 size_t frame_size = channel_count * bytes_per_sample;
5732 size_t frame_count = bytes_to_write / frame_size;
5733
5734 bool force_haptic_path =
5735 property_get_bool("vendor.audio.test_haptic", false);
5736
5737 // extract Haptics data from Audio buffer
5738 bool alloc_haptic_buffer = false;
5739 int haptic_channel_count = adev->haptics_config.channels;
5740 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5741 size_t audio_frame_size = frame_size - haptic_frame_size;
5742 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5743
5744 if (adev->haptic_buffer == NULL) {
5745 alloc_haptic_buffer = true;
5746 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5747 free(adev->haptic_buffer);
5748 adev->haptic_buffer_size = 0;
5749 alloc_haptic_buffer = true;
5750 }
5751
5752 if (alloc_haptic_buffer) {
5753 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005754 if(adev->haptic_buffer == NULL) {
5755 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5756 return -ENOMEM;
5757 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005758 adev->haptic_buffer_size = total_haptic_buffer_size;
5759 }
5760
5761 size_t src_index = 0, aud_index = 0, hap_index = 0;
5762 uint8_t *audio_buffer = (uint8_t *)buffer;
5763 uint8_t *haptic_buffer = adev->haptic_buffer;
5764
5765 // This is required for testing only. This works for stereo data only.
5766 // One channel is fed to audio stream and other to haptic stream for testing.
5767 if (force_haptic_path)
5768 audio_frame_size = haptic_frame_size = bytes_per_sample;
5769
5770 for (size_t i = 0; i < frame_count; i++) {
5771 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5772 audio_frame_size);
5773 aud_index += audio_frame_size;
5774 src_index += audio_frame_size;
5775
5776 if (adev->haptic_pcm)
5777 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5778 haptic_frame_size);
5779 hap_index += haptic_frame_size;
5780 src_index += haptic_frame_size;
5781
5782 // This is required for testing only.
5783 // Discard haptic channel data.
5784 if (force_haptic_path)
5785 src_index += haptic_frame_size;
5786 }
5787
5788 // write to audio pipeline
5789 ret = pcm_write(out->pcm, (void *)audio_buffer,
5790 frame_count * audio_frame_size);
5791
5792 // write to haptics pipeline
5793 if (adev->haptic_pcm)
5794 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5795 frame_count * haptic_frame_size);
5796
5797 return ret;
5798}
5799
Aalique Grahame22e49102018-12-18 14:23:57 -08005800#ifdef NO_AUDIO_OUT
5801static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5802 const void *buffer __unused, size_t bytes)
5803{
5804 struct stream_out *out = (struct stream_out *)stream;
5805
5806 /* No Output device supported other than BT for playback.
5807 * Sleep for the amount of buffer duration
5808 */
5809 lock_output_stream(out);
5810 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5811 (const struct audio_stream_out *)&out->stream) /
5812 out_get_sample_rate(&out->stream.common));
5813 pthread_mutex_unlock(&out->lock);
5814 return bytes;
5815}
5816#endif
5817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005818static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5819 size_t bytes)
5820{
5821 struct stream_out *out = (struct stream_out *)stream;
5822 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005823 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305824 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005825 const size_t frame_size = audio_stream_out_frame_size(stream);
5826 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305827 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005828 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829
Haynes Mathew George380745d2017-10-04 15:27:45 -07005830 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005831 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305832
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305833 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005834
Dhananjay Kumarac341582017-02-23 23:42:25 +05305835 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305836 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305837 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5838 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005839 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305840 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305841 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305842 ALOGD(" %s: sound card is not active/SSR state", __func__);
5843 ret= -EIO;
5844 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305845 }
5846 }
5847
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305848 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305849 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305850 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305851 goto exit;
5852 }
5853
Haynes Mathew George16081042017-05-31 17:16:49 -07005854 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5855 ret = -EINVAL;
5856 goto exit;
5857 }
5858
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005859 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305860 !out->is_iec61937_info_available) {
5861
5862 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5863 out->is_iec61937_info_available = true;
5864 } else if (audio_extn_passthru_is_enabled()) {
5865 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305866 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305867
5868 if((out->format == AUDIO_FORMAT_DTS) ||
5869 (out->format == AUDIO_FORMAT_DTS_HD)) {
5870 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5871 buffer, bytes);
5872 if (ret) {
5873 if (ret != -ENOSYS) {
5874 out->is_iec61937_info_available = false;
5875 ALOGD("iec61937 transmission info not yet updated retry");
5876 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305877 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305878 /* if stream has started and after that there is
5879 * stream config change (iec transmission config)
5880 * then trigger select_device to update backend configuration.
5881 */
5882 out->stream_config_changed = true;
5883 pthread_mutex_lock(&adev->lock);
5884 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305885 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005886 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305887 ret = -EINVAL;
5888 goto exit;
5889 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305890 pthread_mutex_unlock(&adev->lock);
5891 out->stream_config_changed = false;
5892 out->is_iec61937_info_available = true;
5893 }
5894 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305895
Meng Wang4c32fb42020-01-16 17:57:11 +08005896#ifdef AUDIO_GKI_ENABLED
5897 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5898 compr_passthr = out->compr_config.codec->reserved[0];
5899#else
5900 compr_passthr = out->compr_config.codec->compr_passthr;
5901#endif
5902
Garmond Leung317cbf12017-09-13 16:20:50 -07005903 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005904 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305905 (out->is_iec61937_info_available == true)) {
5906 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5907 ret = -EINVAL;
5908 goto exit;
5909 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305910 }
5911 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305912
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005913 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005914 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005915 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5916 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005917 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305918 ret = -EIO;
5919 goto exit;
5920 }
5921 }
5922 }
5923
Weiyin Jiangabedea32020-12-09 12:49:19 +08005924 if (is_usb_out_device_type(&out->device_list) &&
5925 !audio_extn_usb_connected(NULL)) {
5926 ret = -EIO;
5927 goto exit;
5928 }
5929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005930 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005931 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005932 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5933
Eric Laurent150dbfe2013-02-27 14:31:02 -08005934 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005935 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5936 ret = voice_extn_compress_voip_start_output_stream(out);
5937 else
5938 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005939 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005940 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005941 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005942 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005943 goto exit;
5944 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305945 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005946 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005947
5948 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005949 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005950 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305951 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005952 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005953 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305954
5955 if ((out->is_iec61937_info_available == true) &&
5956 (audio_extn_passthru_is_passthrough_stream(out))&&
5957 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5958 ret = -EINVAL;
5959 goto exit;
5960 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305961 if (out->set_dual_mono)
5962 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005963
5964 // log startup time in ms.
5965 simple_stats_log(
5966 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005968
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005969 if (adev->is_channel_status_set == false &&
5970 compare_device_type(&out->device_list,
5971 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005972 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305973 adev->is_channel_status_set = true;
5974 }
5975
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305976 if ((adev->use_old_pspd_mix_ctrl == true) &&
5977 (out->pspd_coeff_sent == false)) {
5978 /*
5979 * Need to resend pspd coefficients after stream started for
5980 * older kernel version as it does not save the coefficients
5981 * and also stream has to be started for coeff to apply.
5982 */
5983 usecase = get_usecase_from_list(adev, out->usecase);
5984 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305985 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305986 out->pspd_coeff_sent = true;
5987 }
5988 }
5989
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005990 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005991 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005992 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005993 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005994 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5995 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305996 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5997 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005998 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305999 out->send_next_track_params = false;
6000 out->is_compr_metadata_avail = false;
6001 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006002 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306003 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306004 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006005
Ashish Jain83a6cc22016-06-28 14:34:17 +05306006 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306007 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306008 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306009 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006010 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306011 return -EINVAL;
6012 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306013 audio_format_t dst_format = out->hal_op_format;
6014 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306015
Dieter Luecking5d57def2018-09-07 14:23:37 +02006016 /* prevent division-by-zero */
6017 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6018 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6019 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6020 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306021 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006022 ATRACE_END();
6023 return -EINVAL;
6024 }
6025
Ashish Jainf1eaa582016-05-23 20:54:24 +05306026 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6027 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6028
Ashish Jain83a6cc22016-06-28 14:34:17 +05306029 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306030 dst_format,
6031 buffer,
6032 src_format,
6033 frames);
6034
Ashish Jain83a6cc22016-06-28 14:34:17 +05306035 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306036 bytes_to_write);
6037
6038 /*Convert written bytes in audio flinger format*/
6039 if (ret > 0)
6040 ret = ((ret * format_to_bitwidth_table[out->format]) /
6041 format_to_bitwidth_table[dst_format]);
6042 }
6043 } else
6044 ret = compress_write(out->compr, buffer, bytes);
6045
Zhou Songc9672822017-08-16 16:01:39 +08006046 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6047 update_frames_written(out, bytes);
6048
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306049 if (ret < 0)
6050 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006051 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306052 /*msg to cb thread only if non blocking write is enabled*/
6053 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306054 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006055 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306056 } else if (-ENETRESET == ret) {
6057 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306058 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306059 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306060 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006061 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306062 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006063 }
Ashish Jain5106d362016-05-11 19:23:33 +05306064
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306065 /* Call compr start only when non-zero bytes of data is there to be rendered */
6066 if (!out->playback_started && ret > 0) {
6067 int status = compress_start(out->compr);
6068 if (status < 0) {
6069 ret = status;
6070 ALOGE("%s: compr start failed with err %d", __func__, errno);
6071 goto exit;
6072 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006073 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006074 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006075 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006076 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006077 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006078
6079 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6080 popcount(out->channel_mask),
6081 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006082 }
6083 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006084 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006085 return ret;
6086 } else {
6087 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006088 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006089 if (out->muted)
6090 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006091 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6092 __func__, frames, frame_size, bytes_to_write);
6093
Aalique Grahame22e49102018-12-18 14:23:57 -08006094 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006095 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6096 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6097 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006098 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6099 int16_t *src = (int16_t *)buffer;
6100 int16_t *dst = (int16_t *)buffer;
6101
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006102 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006103 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006104 "out_write called for %s use case with wrong properties",
6105 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006106
6107 /*
6108 * FIXME: this can be removed once audio flinger mixer supports
6109 * mono output
6110 */
6111
6112 /*
6113 * Code below goes over each frame in the buffer and adds both
6114 * L and R samples and then divides by 2 to convert to mono
6115 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006116 if (channel_count == 2) {
6117 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6118 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6119 }
6120 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006121 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006122 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006123
6124 // Note: since out_get_presentation_position() is called alternating with out_write()
6125 // by AudioFlinger, we can check underruns using the prior timestamp read.
6126 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6127 if (out->last_fifo_valid) {
6128 // compute drain to see if there is an underrun.
6129 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306130 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6131 int64_t frames_by_time =
6132 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6133 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006134 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6135
6136 if (underrun > 0) {
6137 simple_stats_log(&out->fifo_underruns, underrun);
6138
6139 ALOGW("%s: underrun(%lld) "
6140 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6141 __func__,
6142 (long long)out->fifo_underruns.n,
6143 (long long)frames_by_time,
6144 (long long)out->last_fifo_frames_remaining);
6145 }
6146 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6147 }
6148
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306149 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006150
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006151 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006152
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006153 if (out->config.rate)
6154 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6155 out->config.rate;
6156
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006157 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006158 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006160 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006161 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006162 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306163 out->convert_buffer != NULL) {
6164
6165 memcpy_by_audio_format(out->convert_buffer,
6166 out->hal_op_format,
6167 buffer,
6168 out->hal_ip_format,
6169 out->config.period_size * out->config.channels);
6170
6171 ret = pcm_write(out->pcm, out->convert_buffer,
6172 (out->config.period_size *
6173 out->config.channels *
6174 format_to_bitwidth_table[out->hal_op_format]));
6175 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306176 /*
6177 * To avoid underrun in DSP when the application is not pumping
6178 * data at required rate, check for the no. of bytes and ignore
6179 * pcm_write if it is less than actual buffer size.
6180 * It is a work around to a change in compress VOIP driver.
6181 */
6182 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6183 bytes < (out->config.period_size * out->config.channels *
6184 audio_bytes_per_sample(out->format))) {
6185 size_t voip_buf_size =
6186 out->config.period_size * out->config.channels *
6187 audio_bytes_per_sample(out->format);
6188 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6189 __func__, bytes, voip_buf_size);
6190 usleep(((uint64_t)voip_buf_size - bytes) *
6191 1000000 / audio_stream_out_frame_size(stream) /
6192 out_get_sample_rate(&out->stream.common));
6193 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006194 } else {
6195 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6196 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6197 else
6198 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6199 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306200 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006201
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006202 release_out_focus(out);
6203
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306204 if (ret < 0)
6205 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006206 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306207 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006209 }
6210
6211exit:
Zhou Songc9672822017-08-16 16:01:39 +08006212 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306213 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306214 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216 pthread_mutex_unlock(&out->lock);
6217
6218 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006219 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006220 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306221 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306222 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306223 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306224 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306225 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306226 out->standby = true;
6227 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306228 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006229 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6230 /* prevent division-by-zero */
6231 uint32_t stream_size = audio_stream_out_frame_size(stream);
6232 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006233
Dieter Luecking5d57def2018-09-07 14:23:37 +02006234 if ((stream_size == 0) || (srate == 0)) {
6235 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6236 ATRACE_END();
6237 return -EINVAL;
6238 }
6239 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6240 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006241 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306242 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006243 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006244 return ret;
6245 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006246 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006247 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006248 return bytes;
6249}
6250
6251static int out_get_render_position(const struct audio_stream_out *stream,
6252 uint32_t *dsp_frames)
6253{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006254 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006255
6256 if (dsp_frames == NULL)
6257 return -EINVAL;
6258
6259 *dsp_frames = 0;
6260 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006261 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306262
6263 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6264 * this operation and adev_close_output_stream(where out gets reset).
6265 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306266 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006267 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306268 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006269 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306270 return 0;
6271 }
6272
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006273 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306274 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306275 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006276 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306277 if (ret < 0)
6278 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006279 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306280 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006281 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306282 if (-ENETRESET == ret) {
6283 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306284 out->card_status = CARD_STATUS_OFFLINE;
6285 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306286 } else if(ret < 0) {
6287 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306288 ret = -EINVAL;
6289 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306290 /*
6291 * Handle corner case where compress session is closed during SSR
6292 * and timestamp is queried
6293 */
6294 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306295 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306296 } else if (out->prev_card_status_offline) {
6297 ALOGE("ERROR: previously sound card was offline,return error");
6298 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306299 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306300 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006301 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306302 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306303 pthread_mutex_unlock(&out->lock);
6304 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006305 } else if (audio_is_linear_pcm(out->format)) {
6306 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006307 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006308 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006309 } else
6310 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006311}
6312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006313static int out_add_audio_effect(const struct audio_stream *stream __unused,
6314 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006315{
6316 return 0;
6317}
6318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006319static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6320 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006321{
6322 return 0;
6323}
6324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006325static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6326 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006327{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306328 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006329}
6330
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006331static int out_get_presentation_position(const struct audio_stream_out *stream,
6332 uint64_t *frames, struct timespec *timestamp)
6333{
6334 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306335 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006336 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006337
Ashish Jain5106d362016-05-11 19:23:33 +05306338 /* below piece of code is not guarded against any lock because audioFliner serializes
6339 * this operation and adev_close_output_stream( where out gets reset).
6340 */
6341 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306342 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006343 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306344 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6345 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6346 return 0;
6347 }
6348
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006349 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006350
Ashish Jain5106d362016-05-11 19:23:33 +05306351 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6352 ret = compress_get_tstamp(out->compr, &dsp_frames,
6353 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006354 // Adjustment accounts for A2dp encoder latency with offload usecases
6355 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006356 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006357 unsigned long offset =
6358 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6359 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6360 }
Ashish Jain5106d362016-05-11 19:23:33 +05306361 ALOGVV("%s rendered frames %ld sample_rate %d",
6362 __func__, dsp_frames, out->sample_rate);
6363 *frames = dsp_frames;
6364 if (ret < 0)
6365 ret = -errno;
6366 if (-ENETRESET == ret) {
6367 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306368 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306369 ret = -EINVAL;
6370 } else
6371 ret = 0;
6372 /* this is the best we can do */
6373 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006374 } else {
6375 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006376 unsigned int avail;
6377 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006378 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006379 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006380
Andy Hunga1f48fa2019-07-01 18:14:53 -07006381 if (out->kernel_buffer_size > avail) {
6382 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6383 } else {
6384 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6385 __func__, avail, out->kernel_buffer_size);
6386 avail = out->kernel_buffer_size;
6387 frames_temp = out->last_fifo_frames_remaining = 0;
6388 }
6389 out->last_fifo_valid = true;
6390 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6391
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006392 if (out->written >= frames_temp)
6393 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006394
Andy Hunga1f48fa2019-07-01 18:14:53 -07006395 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6396 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6397
Weiyin Jiangd4633762018-03-16 12:05:03 +08006398 // This adjustment accounts for buffering after app processor.
6399 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006400 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006401 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006402 if (signed_frames >= frames_temp)
6403 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006404
Weiyin Jiangd4633762018-03-16 12:05:03 +08006405 // Adjustment accounts for A2dp encoder latency with non offload usecases
6406 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006407 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006408 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6409 if (signed_frames >= frames_temp)
6410 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006411 }
6412
6413 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006414 *frames = signed_frames;
6415 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006416 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006417 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6418 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006419 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306420 *frames = out->written;
6421 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306422 if (is_offload_usecase(out->usecase))
6423 ret = -EINVAL;
6424 else
6425 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006426 }
6427 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006428 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006429 return ret;
6430}
6431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006432static int out_set_callback(struct audio_stream_out *stream,
6433 stream_callback_t callback, void *cookie)
6434{
6435 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006436 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006437
6438 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006439 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006440 out->client_callback = callback;
6441 out->client_cookie = cookie;
6442 if (out->adsp_hdlr_stream_handle) {
6443 ret = audio_extn_adsp_hdlr_stream_set_callback(
6444 out->adsp_hdlr_stream_handle,
6445 callback,
6446 cookie);
6447 if (ret)
6448 ALOGW("%s:adsp hdlr callback registration failed %d",
6449 __func__, ret);
6450 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006451 pthread_mutex_unlock(&out->lock);
6452 return 0;
6453}
6454
6455static int out_pause(struct audio_stream_out* stream)
6456{
6457 struct stream_out *out = (struct stream_out *)stream;
6458 int status = -ENOSYS;
6459 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006460 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006461 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306462 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006463 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006464 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006465 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306466 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306467 status = compress_pause(out->compr);
6468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006469 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006470
Mingming Yin21854652016-04-13 11:54:02 -07006471 if (audio_extn_passthru_is_active()) {
6472 ALOGV("offload use case, pause passthru");
6473 audio_extn_passthru_on_pause(out);
6474 }
6475
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306476 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006477 audio_extn_dts_notify_playback_state(out->usecase, 0,
6478 out->sample_rate, popcount(out->channel_mask),
6479 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006480 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006481 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006482 pthread_mutex_unlock(&out->lock);
6483 }
6484 return status;
6485}
6486
6487static int out_resume(struct audio_stream_out* stream)
6488{
6489 struct stream_out *out = (struct stream_out *)stream;
6490 int status = -ENOSYS;
6491 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006492 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006493 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306494 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006495 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006496 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006497 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306498 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306499 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006500 }
6501 if (!status) {
6502 out->offload_state = OFFLOAD_STATE_PLAYING;
6503 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306504 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006505 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6506 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006507 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006508 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006509 pthread_mutex_unlock(&out->lock);
6510 }
6511 return status;
6512}
6513
6514static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6515{
6516 struct stream_out *out = (struct stream_out *)stream;
6517 int status = -ENOSYS;
6518 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006519 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006520 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006521 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6522 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6523 else
6524 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6525 pthread_mutex_unlock(&out->lock);
6526 }
6527 return status;
6528}
6529
6530static int out_flush(struct audio_stream_out* stream)
6531{
6532 struct stream_out *out = (struct stream_out *)stream;
6533 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006534 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006535 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006536 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006537 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006538 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306539 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006540 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006541 } else {
6542 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306543 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006544 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006545 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006546 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006547 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006548 return 0;
6549 }
6550 return -ENOSYS;
6551}
6552
Haynes Mathew George16081042017-05-31 17:16:49 -07006553static int out_stop(const struct audio_stream_out* stream)
6554{
6555 struct stream_out *out = (struct stream_out *)stream;
6556 struct audio_device *adev = out->dev;
6557 int ret = -ENOSYS;
6558
6559 ALOGV("%s", __func__);
6560 pthread_mutex_lock(&adev->lock);
6561 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6562 out->playback_started && out->pcm != NULL) {
6563 pcm_stop(out->pcm);
6564 ret = stop_output_stream(out);
6565 out->playback_started = false;
6566 }
6567 pthread_mutex_unlock(&adev->lock);
6568 return ret;
6569}
6570
6571static int out_start(const struct audio_stream_out* stream)
6572{
6573 struct stream_out *out = (struct stream_out *)stream;
6574 struct audio_device *adev = out->dev;
6575 int ret = -ENOSYS;
6576
6577 ALOGV("%s", __func__);
6578 pthread_mutex_lock(&adev->lock);
6579 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6580 !out->playback_started && out->pcm != NULL) {
6581 ret = start_output_stream(out);
6582 if (ret == 0) {
6583 out->playback_started = true;
6584 }
6585 }
6586 pthread_mutex_unlock(&adev->lock);
6587 return ret;
6588}
6589
6590/*
6591 * Modify config->period_count based on min_size_frames
6592 */
6593static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6594{
6595 int periodCountRequested = (min_size_frames + config->period_size - 1)
6596 / config->period_size;
6597 int periodCount = MMAP_PERIOD_COUNT_MIN;
6598
6599 ALOGV("%s original config.period_size = %d config.period_count = %d",
6600 __func__, config->period_size, config->period_count);
6601
6602 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6603 periodCount *= 2;
6604 }
6605 config->period_count = periodCount;
6606
6607 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6608}
6609
Phil Burkfe17efd2019-03-25 10:23:35 -07006610// Read offset for the positional timestamp from a persistent vendor property.
6611// This is to workaround apparent inaccuracies in the timing information that
6612// is used by the AAudio timing model. The inaccuracies can cause glitches.
6613static int64_t get_mmap_out_time_offset() {
6614 const int32_t kDefaultOffsetMicros = 0;
6615 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006616 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006617 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6618 return mmap_time_offset_micros * (int64_t)1000;
6619}
6620
Haynes Mathew George16081042017-05-31 17:16:49 -07006621static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6622 int32_t min_size_frames,
6623 struct audio_mmap_buffer_info *info)
6624{
6625 struct stream_out *out = (struct stream_out *)stream;
6626 struct audio_device *adev = out->dev;
6627 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006628 unsigned int offset1 = 0;
6629 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006630 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006631 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006632 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006633
Arun Mirpuri5d170872019-03-26 13:21:31 -07006634 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306635 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006636 pthread_mutex_lock(&adev->lock);
6637
Sharad Sanglec6f32552018-05-04 16:15:38 +05306638 if (CARD_STATUS_OFFLINE == out->card_status ||
6639 CARD_STATUS_OFFLINE == adev->card_status) {
6640 ALOGW("out->card_status or adev->card_status offline, try again");
6641 ret = -EIO;
6642 goto exit;
6643 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306644 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006645 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6646 ret = -EINVAL;
6647 goto exit;
6648 }
6649 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6650 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6651 ret = -ENOSYS;
6652 goto exit;
6653 }
6654 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6655 if (out->pcm_device_id < 0) {
6656 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6657 __func__, out->pcm_device_id, out->usecase);
6658 ret = -EINVAL;
6659 goto exit;
6660 }
6661
6662 adjust_mmap_period_count(&out->config, min_size_frames);
6663
Arun Mirpuri5d170872019-03-26 13:21:31 -07006664 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006665 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6666 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6667 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306668 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306669 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6670 out->card_status = CARD_STATUS_OFFLINE;
6671 adev->card_status = CARD_STATUS_OFFLINE;
6672 ret = -EIO;
6673 goto exit;
6674 }
6675
Haynes Mathew George16081042017-05-31 17:16:49 -07006676 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6677 step = "open";
6678 ret = -ENODEV;
6679 goto exit;
6680 }
6681 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6682 if (ret < 0) {
6683 step = "begin";
6684 goto exit;
6685 }
juyuchen626833d2019-06-04 16:48:02 +08006686
6687 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006688 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006689 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006690 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006691 ret = platform_get_mmap_data_fd(adev->platform,
6692 out->pcm_device_id, 0 /*playback*/,
6693 &info->shared_memory_fd,
6694 &mmap_size);
6695 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006696 // Fall back to non exclusive mode
6697 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6698 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006699 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6700 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6701
Arun Mirpuri5d170872019-03-26 13:21:31 -07006702 if (mmap_size < buffer_size) {
6703 step = "mmap";
6704 goto exit;
6705 }
juyuchen626833d2019-06-04 16:48:02 +08006706 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006707 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006708 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006709 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006710
6711 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6712 if (ret < 0) {
6713 step = "commit";
6714 goto exit;
6715 }
6716
Phil Burkfe17efd2019-03-25 10:23:35 -07006717 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6718
Haynes Mathew George16081042017-05-31 17:16:49 -07006719 out->standby = false;
6720 ret = 0;
6721
Arun Mirpuri5d170872019-03-26 13:21:31 -07006722 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006723 __func__, info->shared_memory_address, info->buffer_size_frames);
6724
6725exit:
6726 if (ret != 0) {
6727 if (out->pcm == NULL) {
6728 ALOGE("%s: %s - %d", __func__, step, ret);
6729 } else {
6730 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6731 pcm_close(out->pcm);
6732 out->pcm = NULL;
6733 }
6734 }
6735 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306736 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006737 return ret;
6738}
6739
6740static int out_get_mmap_position(const struct audio_stream_out *stream,
6741 struct audio_mmap_position *position)
6742{
6743 struct stream_out *out = (struct stream_out *)stream;
6744 ALOGVV("%s", __func__);
6745 if (position == NULL) {
6746 return -EINVAL;
6747 }
6748 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006749 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006750 return -ENOSYS;
6751 }
6752 if (out->pcm == NULL) {
6753 return -ENOSYS;
6754 }
6755
6756 struct timespec ts = { 0, 0 };
6757 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6758 if (ret < 0) {
6759 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6760 return ret;
6761 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006762 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6763 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006764 return 0;
6765}
6766
6767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006768/** audio_stream_in implementation **/
6769static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6770{
6771 struct stream_in *in = (struct stream_in *)stream;
6772
6773 return in->config.rate;
6774}
6775
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006776static int in_set_sample_rate(struct audio_stream *stream __unused,
6777 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006778{
6779 return -ENOSYS;
6780}
6781
6782static size_t in_get_buffer_size(const struct audio_stream *stream)
6783{
6784 struct stream_in *in = (struct stream_in *)stream;
6785
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006786 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6787 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006788 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6789 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306790 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306791 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006792
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006793 return in->config.period_size * in->af_period_multiplier *
6794 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006795}
6796
6797static uint32_t in_get_channels(const struct audio_stream *stream)
6798{
6799 struct stream_in *in = (struct stream_in *)stream;
6800
6801 return in->channel_mask;
6802}
6803
6804static audio_format_t in_get_format(const struct audio_stream *stream)
6805{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006806 struct stream_in *in = (struct stream_in *)stream;
6807
6808 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006809}
6810
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006811static int in_set_format(struct audio_stream *stream __unused,
6812 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006813{
6814 return -ENOSYS;
6815}
6816
6817static int in_standby(struct audio_stream *stream)
6818{
6819 struct stream_in *in = (struct stream_in *)stream;
6820 struct audio_device *adev = in->dev;
6821 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306822 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6823 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006824 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306825
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006826 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006827 if (!in->standby && in->is_st_session) {
6828 ALOGD("%s: sound trigger pcm stop lab", __func__);
6829 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006830 if (adev->num_va_sessions > 0)
6831 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006832 in->standby = 1;
6833 }
6834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006836 if (adev->adm_deregister_stream)
6837 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6838
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006839 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006841 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006842 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006843 voice_extn_compress_voip_close_input_stream(stream);
6844 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006845 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6846 do_stop = in->capture_started;
6847 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006848 if (in->mmap_shared_memory_fd >= 0) {
6849 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6850 __func__, in->mmap_shared_memory_fd);
6851 close(in->mmap_shared_memory_fd);
6852 in->mmap_shared_memory_fd = -1;
6853 }
Zhou Songa8895042016-07-05 17:54:22 +08006854 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306855 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306856 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006857 }
6858
Arun Mirpuri5d170872019-03-26 13:21:31 -07006859 if (in->pcm) {
6860 ATRACE_BEGIN("pcm_in_close");
6861 pcm_close(in->pcm);
6862 ATRACE_END();
6863 in->pcm = NULL;
6864 }
6865
Carter Hsu2e429db2019-05-14 18:50:52 +08006866 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006867 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006868
George Gao3018ede2019-10-23 13:23:00 -07006869 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6870 if (adev->num_va_sessions > 0)
6871 adev->num_va_sessions--;
6872 }
Quinn Malef6050362019-01-30 15:55:40 -08006873
Eric Laurent150dbfe2013-02-27 14:31:02 -08006874 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006875 }
6876 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006877 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878 return status;
6879}
6880
Aalique Grahame22e49102018-12-18 14:23:57 -08006881static int in_dump(const struct audio_stream *stream,
6882 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006883{
Aalique Grahame22e49102018-12-18 14:23:57 -08006884 struct stream_in *in = (struct stream_in *)stream;
6885
6886 // We try to get the lock for consistency,
6887 // but it isn't necessary for these variables.
6888 // If we're not in standby, we may be blocked on a read.
6889 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6890 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6891 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6892 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6893
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006894 char buffer[256]; // for statistics formatting
6895 if (in->start_latency_ms.n > 0) {
6896 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6897 dprintf(fd, " Start latency ms: %s\n", buffer);
6898 }
6899
Aalique Grahame22e49102018-12-18 14:23:57 -08006900 if (locked) {
6901 pthread_mutex_unlock(&in->lock);
6902 }
6903
6904 // dump error info
6905 (void)error_log_dump(
6906 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006908 return 0;
6909}
6910
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306911static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6912{
6913 if (!stream || !parms)
6914 return;
6915
6916 struct stream_in *in = (struct stream_in *)stream;
6917 struct audio_device *adev = in->dev;
6918
6919 card_status_t status;
6920 int card;
6921 if (parse_snd_card_status(parms, &card, &status) < 0)
6922 return;
6923
6924 pthread_mutex_lock(&adev->lock);
6925 bool valid_cb = (card == adev->snd_card);
6926 pthread_mutex_unlock(&adev->lock);
6927
6928 if (!valid_cb)
6929 return;
6930
6931 lock_input_stream(in);
6932 if (in->card_status != status)
6933 in->card_status = status;
6934 pthread_mutex_unlock(&in->lock);
6935
6936 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6937 use_case_table[in->usecase],
6938 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6939
6940 // a better solution would be to report error back to AF and let
6941 // it put the stream to standby
6942 if (status == CARD_STATUS_OFFLINE)
6943 in_standby(&in->stream.common);
6944
6945 return;
6946}
6947
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006948int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006949 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006950 audio_source_t source)
6951{
6952 struct audio_device *adev = in->dev;
6953 int ret = 0;
6954
6955 lock_input_stream(in);
6956 pthread_mutex_lock(&adev->lock);
6957
6958 /* no audio source uses val == 0 */
6959 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6960 in->source = source;
6961 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6962 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6963 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6964 (in->config.rate == 8000 || in->config.rate == 16000 ||
6965 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6966 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6967 ret = voice_extn_compress_voip_open_input_stream(in);
6968 if (ret != 0) {
6969 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6970 __func__, ret);
6971 }
6972 }
6973 }
6974
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006975 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6976 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006977 // Workaround: If routing to an non existing usb device, fail gracefully
6978 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006979 struct str_parms *usb_addr =
6980 str_parms_create_str(get_usb_device_address(devices));
6981 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08006982 !audio_extn_usb_connected(NULL)) {
6983 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006984 ret = -ENOSYS;
6985 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006986 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006987 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006988 if (!in->standby && !in->is_st_session) {
6989 ALOGV("update input routing change");
6990 // inform adm before actual routing to prevent glitches.
6991 if (adev->adm_on_routing_change) {
6992 adev->adm_on_routing_change(adev->adm_data,
6993 in->capture_handle);
6994 ret = select_devices(adev, in->usecase);
6995 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6996 adev->adm_routing_changed = true;
6997 }
6998 }
6999 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007000 if (usb_addr)
7001 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007002 }
7003 pthread_mutex_unlock(&adev->lock);
7004 pthread_mutex_unlock(&in->lock);
7005
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007006 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007007 return ret;
7008}
7009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007010static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7011{
7012 struct stream_in *in = (struct stream_in *)stream;
7013 struct audio_device *adev = in->dev;
7014 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007015 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307016 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007017
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307018 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007019 parms = str_parms_create_str(kvpairs);
7020
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307021 if (!parms)
7022 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007023 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007024 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007025
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307026 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7027 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307028 strlcpy(in->profile, value, sizeof(in->profile));
7029 ALOGV("updating stream profile with value '%s'", in->profile);
7030 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7031 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007032 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307033 in->sample_rate, in->bit_width,
7034 in->profile, &in->app_type_cfg);
7035 }
7036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007037 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007038 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007039
7040 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307041error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307042 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007043}
7044
7045static char* in_get_parameters(const struct audio_stream *stream,
7046 const char *keys)
7047{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007048 struct stream_in *in = (struct stream_in *)stream;
7049 struct str_parms *query = str_parms_create_str(keys);
7050 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007051 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007052
7053 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007054 if (reply) {
7055 str_parms_destroy(reply);
7056 }
7057 if (query) {
7058 str_parms_destroy(query);
7059 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007060 ALOGE("in_get_parameters: failed to create query or reply");
7061 return NULL;
7062 }
7063
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007064 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007065
7066 voice_extn_in_get_parameters(in, query, reply);
7067
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007068 stream_get_parameter_channels(query, reply,
7069 &in->supported_channel_masks[0]);
7070 stream_get_parameter_formats(query, reply,
7071 &in->supported_formats[0]);
7072 stream_get_parameter_rates(query, reply,
7073 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007074 str = str_parms_to_str(reply);
7075 str_parms_destroy(query);
7076 str_parms_destroy(reply);
7077
7078 ALOGV("%s: exit: returns - %s", __func__, str);
7079 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007080}
7081
Aalique Grahame22e49102018-12-18 14:23:57 -08007082static int in_set_gain(struct audio_stream_in *stream,
7083 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007084{
Aalique Grahame22e49102018-12-18 14:23:57 -08007085 struct stream_in *in = (struct stream_in *)stream;
7086 char mixer_ctl_name[128];
7087 struct mixer_ctl *ctl;
7088 int ctl_value;
7089
7090 ALOGV("%s: gain %f", __func__, gain);
7091
7092 if (stream == NULL)
7093 return -EINVAL;
7094
7095 /* in_set_gain() only used to silence MMAP capture for now */
7096 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7097 return -ENOSYS;
7098
7099 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7100
7101 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7102 if (!ctl) {
7103 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7104 __func__, mixer_ctl_name);
7105 return -ENOSYS;
7106 }
7107
7108 if (gain < RECORD_GAIN_MIN)
7109 gain = RECORD_GAIN_MIN;
7110 else if (gain > RECORD_GAIN_MAX)
7111 gain = RECORD_GAIN_MAX;
7112 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7113
7114 mixer_ctl_set_value(ctl, 0, ctl_value);
7115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007116 return 0;
7117}
7118
7119static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7120 size_t bytes)
7121{
7122 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307123
7124 if (in == NULL) {
7125 ALOGE("%s: stream_in ptr is NULL", __func__);
7126 return -EINVAL;
7127 }
7128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007129 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307130 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307131 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007132
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007133 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307134
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007135 if (in->is_st_session) {
7136 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7137 /* Read from sound trigger HAL */
7138 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007139 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007140 if (adev->num_va_sessions < UINT_MAX)
7141 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007142 in->standby = 0;
7143 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007144 pthread_mutex_unlock(&in->lock);
7145 return bytes;
7146 }
7147
Haynes Mathew George16081042017-05-31 17:16:49 -07007148 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7149 ret = -ENOSYS;
7150 goto exit;
7151 }
7152
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007153 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7154 !in->standby && adev->adm_routing_changed) {
7155 ret = -ENOSYS;
7156 goto exit;
7157 }
7158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007159 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007160 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7161
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007162 pthread_mutex_lock(&adev->lock);
7163 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7164 ret = voice_extn_compress_voip_start_input_stream(in);
7165 else
7166 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007167 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7168 if (adev->num_va_sessions < UINT_MAX)
7169 adev->num_va_sessions++;
7170 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007171 pthread_mutex_unlock(&adev->lock);
7172 if (ret != 0) {
7173 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007174 }
7175 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007176
7177 // log startup time in ms.
7178 simple_stats_log(
7179 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007181
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307182 /* Avoid read if capture_stopped is set */
7183 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7184 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7185 ret = -EINVAL;
7186 goto exit;
7187 }
7188
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007189 // what's the duration requested by the client?
7190 long ns = 0;
7191
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307192 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007193 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7194 in->config.rate;
7195
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007196 ret = request_in_focus(in, ns);
7197 if (ret != 0)
7198 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007199 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007200
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307201 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307202 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7203 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307204 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007205 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307206 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007207 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007208 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007209 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007210 } else if (audio_extn_ffv_get_stream() == in) {
7211 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307212 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007213 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307214 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7215 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7216 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7217 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307218 ret = -EINVAL;
7219 goto exit;
7220 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307221 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307222 ret = -errno;
7223 }
7224 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307225 /* bytes read is always set to bytes for non compress usecases */
7226 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007227 }
7228
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007229 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007231 /*
Quinn Malef6050362019-01-30 15:55:40 -08007232 * Instead of writing zeroes here, we could trust the hardware to always
7233 * provide zeroes when muted. This is also muted with voice recognition
7234 * usecases so that other clients do not have access to voice recognition
7235 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236 */
Quinn Malef6050362019-01-30 15:55:40 -08007237 if ((ret == 0 && voice_get_mic_mute(adev) &&
7238 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007239 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7240 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007241 (adev->num_va_sessions &&
7242 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7243 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7244 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245 memset(buffer, 0, bytes);
7246
7247exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307248 frame_size = audio_stream_in_frame_size(stream);
7249 if (frame_size > 0)
7250 in->frames_read += bytes_read/frame_size;
7251
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007252 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307253 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007254 pthread_mutex_unlock(&in->lock);
7255
7256 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307257 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307258 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307259 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307260 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307261 in->standby = true;
7262 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307263 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307264 bytes_read = bytes;
7265 memset(buffer, 0, bytes);
7266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007267 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007268 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7269 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007270 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307271 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307272 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007273 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307274 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007275}
7276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007277static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007278{
7279 return 0;
7280}
7281
Aalique Grahame22e49102018-12-18 14:23:57 -08007282static int in_get_capture_position(const struct audio_stream_in *stream,
7283 int64_t *frames, int64_t *time)
7284{
7285 if (stream == NULL || frames == NULL || time == NULL) {
7286 return -EINVAL;
7287 }
7288 struct stream_in *in = (struct stream_in *)stream;
7289 int ret = -ENOSYS;
7290
7291 lock_input_stream(in);
7292 // note: ST sessions do not close the alsa pcm driver synchronously
7293 // on standby. Therefore, we may return an error even though the
7294 // pcm stream is still opened.
7295 if (in->standby) {
7296 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7297 "%s stream in standby but pcm not NULL for non ST session", __func__);
7298 goto exit;
7299 }
7300 if (in->pcm) {
7301 struct timespec timestamp;
7302 unsigned int avail;
7303 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7304 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007305 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007306 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007307 ret = 0;
7308 }
7309 }
7310exit:
7311 pthread_mutex_unlock(&in->lock);
7312 return ret;
7313}
7314
Carter Hsu2e429db2019-05-14 18:50:52 +08007315static int in_update_effect_list(bool add, effect_handle_t effect,
7316 struct listnode *head)
7317{
7318 struct listnode *node;
7319 struct in_effect_list *elist = NULL;
7320 struct in_effect_list *target = NULL;
7321 int ret = 0;
7322
7323 if (!head)
7324 return ret;
7325
7326 list_for_each(node, head) {
7327 elist = node_to_item(node, struct in_effect_list, list);
7328 if (elist->handle == effect) {
7329 target = elist;
7330 break;
7331 }
7332 }
7333
7334 if (add) {
7335 if (target) {
7336 ALOGD("effect %p already exist", effect);
7337 return ret;
7338 }
7339
7340 target = (struct in_effect_list *)
7341 calloc(1, sizeof(struct in_effect_list));
7342
7343 if (!target) {
7344 ALOGE("%s:fail to allocate memory", __func__);
7345 return -ENOMEM;
7346 }
7347
7348 target->handle = effect;
7349 list_add_tail(head, &target->list);
7350 } else {
7351 if (target) {
7352 list_remove(&target->list);
7353 free(target);
7354 }
7355 }
7356
7357 return ret;
7358}
7359
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007360static int add_remove_audio_effect(const struct audio_stream *stream,
7361 effect_handle_t effect,
7362 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007363{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007364 struct stream_in *in = (struct stream_in *)stream;
7365 int status = 0;
7366 effect_descriptor_t desc;
7367
7368 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007369 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7370
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007371 if (status != 0)
7372 return status;
7373
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007374 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007375 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007376 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007377 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7378 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007379 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007380
7381 in_update_effect_list(enable, effect, &in->aec_list);
7382 enable = !list_empty(&in->aec_list);
7383 if (enable == in->enable_aec)
7384 goto exit;
7385
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007386 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007387 ALOGD("AEC enable %d", enable);
7388
Aalique Grahame22e49102018-12-18 14:23:57 -08007389 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7390 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7391 in->dev->enable_voicerx = enable;
7392 struct audio_usecase *usecase;
7393 struct listnode *node;
7394 list_for_each(node, &in->dev->usecase_list) {
7395 usecase = node_to_item(node, struct audio_usecase, list);
7396 if (usecase->type == PCM_PLAYBACK)
7397 select_devices(in->dev, usecase->id);
7398 }
7399 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007400 if (!in->standby) {
7401 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7402 select_devices(in->dev, in->usecase);
7403 }
7404
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007405 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007406 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7407
7408 in_update_effect_list(enable, effect, &in->ns_list);
7409 enable = !list_empty(&in->ns_list);
7410 if (enable == in->enable_ns)
7411 goto exit;
7412
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007413 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007414 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007415 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007416 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7417 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007418 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7419 select_devices(in->dev, in->usecase);
7420 } else
7421 select_devices(in->dev, in->usecase);
7422 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007423 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007424exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007425 pthread_mutex_unlock(&in->dev->lock);
7426 pthread_mutex_unlock(&in->lock);
7427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007428 return 0;
7429}
7430
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007431static int in_add_audio_effect(const struct audio_stream *stream,
7432 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007433{
Eric Laurent994a6932013-07-17 11:51:42 -07007434 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007435 return add_remove_audio_effect(stream, effect, true);
7436}
7437
7438static int in_remove_audio_effect(const struct audio_stream *stream,
7439 effect_handle_t effect)
7440{
Eric Laurent994a6932013-07-17 11:51:42 -07007441 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007442 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007443}
7444
Haynes Mathew George16081042017-05-31 17:16:49 -07007445static int in_stop(const struct audio_stream_in* stream)
7446{
7447 struct stream_in *in = (struct stream_in *)stream;
7448 struct audio_device *adev = in->dev;
7449
7450 int ret = -ENOSYS;
7451 ALOGV("%s", __func__);
7452 pthread_mutex_lock(&adev->lock);
7453 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7454 in->capture_started && in->pcm != NULL) {
7455 pcm_stop(in->pcm);
7456 ret = stop_input_stream(in);
7457 in->capture_started = false;
7458 }
7459 pthread_mutex_unlock(&adev->lock);
7460 return ret;
7461}
7462
7463static int in_start(const struct audio_stream_in* stream)
7464{
7465 struct stream_in *in = (struct stream_in *)stream;
7466 struct audio_device *adev = in->dev;
7467 int ret = -ENOSYS;
7468
7469 ALOGV("%s in %p", __func__, in);
7470 pthread_mutex_lock(&adev->lock);
7471 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7472 !in->capture_started && in->pcm != NULL) {
7473 if (!in->capture_started) {
7474 ret = start_input_stream(in);
7475 if (ret == 0) {
7476 in->capture_started = true;
7477 }
7478 }
7479 }
7480 pthread_mutex_unlock(&adev->lock);
7481 return ret;
7482}
7483
Phil Burke0a86d12019-02-16 22:28:11 -08007484// Read offset for the positional timestamp from a persistent vendor property.
7485// This is to workaround apparent inaccuracies in the timing information that
7486// is used by the AAudio timing model. The inaccuracies can cause glitches.
7487static int64_t in_get_mmap_time_offset() {
7488 const int32_t kDefaultOffsetMicros = 0;
7489 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007490 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007491 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7492 return mmap_time_offset_micros * (int64_t)1000;
7493}
7494
Haynes Mathew George16081042017-05-31 17:16:49 -07007495static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7496 int32_t min_size_frames,
7497 struct audio_mmap_buffer_info *info)
7498{
7499 struct stream_in *in = (struct stream_in *)stream;
7500 struct audio_device *adev = in->dev;
7501 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007502 unsigned int offset1 = 0;
7503 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007504 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007505 uint32_t mmap_size = 0;
7506 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007507
7508 pthread_mutex_lock(&adev->lock);
7509 ALOGV("%s in %p", __func__, in);
7510
Sharad Sanglec6f32552018-05-04 16:15:38 +05307511 if (CARD_STATUS_OFFLINE == in->card_status||
7512 CARD_STATUS_OFFLINE == adev->card_status) {
7513 ALOGW("in->card_status or adev->card_status offline, try again");
7514 ret = -EIO;
7515 goto exit;
7516 }
7517
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307518 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007519 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7520 ret = -EINVAL;
7521 goto exit;
7522 }
7523 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7524 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7525 ALOGV("%s in %p", __func__, in);
7526 ret = -ENOSYS;
7527 goto exit;
7528 }
7529 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7530 if (in->pcm_device_id < 0) {
7531 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7532 __func__, in->pcm_device_id, in->usecase);
7533 ret = -EINVAL;
7534 goto exit;
7535 }
7536
7537 adjust_mmap_period_count(&in->config, min_size_frames);
7538
7539 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7540 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7541 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7542 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307543 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307544 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7545 in->card_status = CARD_STATUS_OFFLINE;
7546 adev->card_status = CARD_STATUS_OFFLINE;
7547 ret = -EIO;
7548 goto exit;
7549 }
7550
Haynes Mathew George16081042017-05-31 17:16:49 -07007551 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7552 step = "open";
7553 ret = -ENODEV;
7554 goto exit;
7555 }
7556
7557 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7558 if (ret < 0) {
7559 step = "begin";
7560 goto exit;
7561 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007562
juyuchen626833d2019-06-04 16:48:02 +08007563 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007564 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7565 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7566 info->burst_size_frames = in->config.period_size;
7567 ret = platform_get_mmap_data_fd(adev->platform,
7568 in->pcm_device_id, 1 /*capture*/,
7569 &info->shared_memory_fd,
7570 &mmap_size);
7571 if (ret < 0) {
7572 // Fall back to non exclusive mode
7573 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7574 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007575 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7576 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7577
Arun Mirpuri5d170872019-03-26 13:21:31 -07007578 if (mmap_size < buffer_size) {
7579 step = "mmap";
7580 goto exit;
7581 }
juyuchen626833d2019-06-04 16:48:02 +08007582 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007583 }
7584
7585 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007586
7587 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7588 if (ret < 0) {
7589 step = "commit";
7590 goto exit;
7591 }
7592
Phil Burke0a86d12019-02-16 22:28:11 -08007593 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7594
Haynes Mathew George16081042017-05-31 17:16:49 -07007595 in->standby = false;
7596 ret = 0;
7597
7598 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7599 __func__, info->shared_memory_address, info->buffer_size_frames);
7600
7601exit:
7602 if (ret != 0) {
7603 if (in->pcm == NULL) {
7604 ALOGE("%s: %s - %d", __func__, step, ret);
7605 } else {
7606 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7607 pcm_close(in->pcm);
7608 in->pcm = NULL;
7609 }
7610 }
7611 pthread_mutex_unlock(&adev->lock);
7612 return ret;
7613}
7614
7615static int in_get_mmap_position(const struct audio_stream_in *stream,
7616 struct audio_mmap_position *position)
7617{
7618 struct stream_in *in = (struct stream_in *)stream;
7619 ALOGVV("%s", __func__);
7620 if (position == NULL) {
7621 return -EINVAL;
7622 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307623 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007624 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307625 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007626 return -ENOSYS;
7627 }
7628 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307629 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007630 return -ENOSYS;
7631 }
7632 struct timespec ts = { 0, 0 };
7633 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7634 if (ret < 0) {
7635 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307636 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007637 return ret;
7638 }
Phil Burke0a86d12019-02-16 22:28:11 -08007639 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7640 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307641 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007642 return 0;
7643}
7644
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307645static int in_get_active_microphones(const struct audio_stream_in *stream,
7646 struct audio_microphone_characteristic_t *mic_array,
7647 size_t *mic_count) {
7648 struct stream_in *in = (struct stream_in *)stream;
7649 struct audio_device *adev = in->dev;
7650 ALOGVV("%s", __func__);
7651
7652 lock_input_stream(in);
7653 pthread_mutex_lock(&adev->lock);
7654 int ret = platform_get_active_microphones(adev->platform,
7655 audio_channel_count_from_in_mask(in->channel_mask),
7656 in->usecase, mic_array, mic_count);
7657 pthread_mutex_unlock(&adev->lock);
7658 pthread_mutex_unlock(&in->lock);
7659
7660 return ret;
7661}
7662
7663static int adev_get_microphones(const struct audio_hw_device *dev,
7664 struct audio_microphone_characteristic_t *mic_array,
7665 size_t *mic_count) {
7666 struct audio_device *adev = (struct audio_device *)dev;
7667 ALOGVV("%s", __func__);
7668
7669 pthread_mutex_lock(&adev->lock);
7670 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7671 pthread_mutex_unlock(&adev->lock);
7672
7673 return ret;
7674}
juyuchendb308c22019-01-21 11:57:17 -07007675
7676static void in_update_sink_metadata(struct audio_stream_in *stream,
7677 const struct sink_metadata *sink_metadata) {
7678
7679 if (stream == NULL
7680 || sink_metadata == NULL
7681 || sink_metadata->tracks == NULL) {
7682 return;
7683 }
7684
7685 int error = 0;
7686 struct stream_in *in = (struct stream_in *)stream;
7687 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007688 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007689 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007690
7691 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007692
7693 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007694 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007695
7696 lock_input_stream(in);
7697 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007698 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007699
Zhou Song62ea0282020-03-22 19:53:01 +08007700 is_ha_usecase = adev->ha_proxy_enable ?
7701 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7702 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7703 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007704 && adev->voice_tx_output != NULL) {
7705 /* Use the rx device from afe-proxy record to route voice call because
7706 there is no routing if tx device is on primary hal and rx device
7707 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007708 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007709
7710 if (!voice_is_call_state_active(adev)) {
7711 if (adev->mode == AUDIO_MODE_IN_CALL) {
7712 adev->current_call_output = adev->voice_tx_output;
7713 error = voice_start_call(adev);
7714 if (error != 0)
7715 ALOGE("%s: start voice call failed %d", __func__, error);
7716 }
7717 } else {
7718 adev->current_call_output = adev->voice_tx_output;
7719 voice_update_devices_for_all_voice_usecases(adev);
7720 }
7721 }
7722
7723 pthread_mutex_unlock(&adev->lock);
7724 pthread_mutex_unlock(&in->lock);
7725}
7726
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307727int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007728 audio_io_handle_t handle,
7729 audio_devices_t devices,
7730 audio_output_flags_t flags,
7731 struct audio_config *config,
7732 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007733 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007734{
7735 struct audio_device *adev = (struct audio_device *)dev;
7736 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307737 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007738 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007739 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307740 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007741 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7742 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7743 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7744 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007745 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007746 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7747 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007748 bool force_haptic_path =
7749 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007750 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007751#ifdef AUDIO_GKI_ENABLED
7752 __s32 *generic_dec;
7753#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007754 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007755
kunleizdff872d2018-08-20 14:40:33 +08007756 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007757 is_usb_dev = false;
7758 devices = AUDIO_DEVICE_OUT_SPEAKER;
7759 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7760 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007761 if (config->format == AUDIO_FORMAT_DEFAULT)
7762 config->format = AUDIO_FORMAT_PCM_16_BIT;
7763 if (config->sample_rate == 0)
7764 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7765 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7766 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007767 }
7768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007769 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007771 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7772
Mingming Yin3a941d42016-02-17 18:08:05 -08007773 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007774 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7775 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307776
7777
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007778 if (!out) {
7779 return -ENOMEM;
7780 }
7781
Haynes Mathew George204045b2015-02-25 20:32:03 -08007782 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007783 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007784 pthread_mutexattr_init(&latch_attr);
7785 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
7786 pthread_mutex_init(&out->latch_lock, &latch_attr);
7787 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08007788 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007789 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007791 if (devices == AUDIO_DEVICE_NONE)
7792 devices = AUDIO_DEVICE_OUT_SPEAKER;
7793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007794 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007795 list_init(&out->device_list);
7796 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007797 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007798 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007799 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307800 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307801 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7802 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7803 else
7804 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007805 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007806 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007807 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307808 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307809 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007810 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007811 out->hal_output_suspend_supported = 0;
7812 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307813 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307814 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307815 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007816 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007817
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307818 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307819 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007820 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7821
Aalique Grahame22e49102018-12-18 14:23:57 -08007822 if (direct_dev &&
7823 (audio_is_linear_pcm(out->format) ||
7824 config->format == AUDIO_FORMAT_DEFAULT) &&
7825 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7826 audio_format_t req_format = config->format;
7827 audio_channel_mask_t req_channel_mask = config->channel_mask;
7828 uint32_t req_sample_rate = config->sample_rate;
7829
7830 pthread_mutex_lock(&adev->lock);
7831 if (is_hdmi) {
7832 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7833 ret = read_hdmi_sink_caps(out);
7834 if (config->sample_rate == 0)
7835 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7836 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7837 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7838 if (config->format == AUDIO_FORMAT_DEFAULT)
7839 config->format = AUDIO_FORMAT_PCM_16_BIT;
7840 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007841 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7842 &config->format,
7843 &out->supported_formats[0],
7844 MAX_SUPPORTED_FORMATS,
7845 &config->channel_mask,
7846 &out->supported_channel_masks[0],
7847 MAX_SUPPORTED_CHANNEL_MASKS,
7848 &config->sample_rate,
7849 &out->supported_sample_rates[0],
7850 MAX_SUPPORTED_SAMPLE_RATES);
7851 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007852 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007853
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007854 pthread_mutex_unlock(&adev->lock);
7855 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007856 if (ret == -ENOSYS) {
7857 /* ignore and go with default */
7858 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007859 }
7860 // For MMAP NO IRQ, allow conversions in ADSP
7861 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7862 goto error_open;
7863 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007864 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007865 goto error_open;
7866 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007867
7868 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7869 config->sample_rate = req_sample_rate;
7870 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7871 config->channel_mask = req_channel_mask;
7872 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7873 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007874 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007875
7876 out->sample_rate = config->sample_rate;
7877 out->channel_mask = config->channel_mask;
7878 out->format = config->format;
7879 if (is_hdmi) {
7880 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7881 out->config = pcm_config_hdmi_multi;
7882 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7883 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7884 out->config = pcm_config_mmap_playback;
7885 out->stream.start = out_start;
7886 out->stream.stop = out_stop;
7887 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7888 out->stream.get_mmap_position = out_get_mmap_position;
7889 } else {
7890 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7891 out->config = pcm_config_hifi;
7892 }
7893
7894 out->config.rate = out->sample_rate;
7895 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7896 if (is_hdmi) {
7897 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7898 audio_bytes_per_sample(out->format));
7899 }
7900 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007901 }
7902
Derek Chenf6318be2017-06-12 17:16:24 -04007903 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007904 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007905 /* extract car audio stream index */
7906 out->car_audio_stream =
7907 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7908 if (out->car_audio_stream < 0) {
7909 ALOGE("%s: invalid car audio stream %x",
7910 __func__, out->car_audio_stream);
7911 ret = -EINVAL;
7912 goto error_open;
7913 }
Derek Chen5f67a942020-02-24 23:08:13 -08007914 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007915 }
7916
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007917 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007918 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007919 if (!voice_extn_is_compress_voip_supported()) {
7920 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7921 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007922 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307923 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007924 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7925 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007926 out->volume_l = INVALID_OUT_VOLUME;
7927 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007928
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007929 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007930 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007931 uint32_t channel_count =
7932 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307933 out->config.channels = channel_count;
7934
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007935 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7936 out->sample_rate, out->format,
7937 channel_count, false);
7938 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7939 if (frame_size != 0)
7940 out->config.period_size = buffer_size / frame_size;
7941 else
7942 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007943 }
7944 } else {
7945 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7946 voice_extn_compress_voip_is_active(out->dev)) &&
7947 (voice_extn_compress_voip_is_config_supported(config))) {
7948 ret = voice_extn_compress_voip_open_output_stream(out);
7949 if (ret != 0) {
7950 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7951 __func__, ret);
7952 goto error_open;
7953 }
Sujin Panicker19027262019-09-16 18:28:06 +05307954 } else {
7955 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7956 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007957 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007958 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007959 } else if (audio_is_linear_pcm(out->format) &&
7960 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7961 out->channel_mask = config->channel_mask;
7962 out->sample_rate = config->sample_rate;
7963 out->format = config->format;
7964 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7965 // does this change?
7966 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7967 out->config.rate = config->sample_rate;
7968 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7969 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7970 audio_bytes_per_sample(config->format));
7971 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007972 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307973 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307974 pthread_mutex_lock(&adev->lock);
7975 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7976 pthread_mutex_unlock(&adev->lock);
7977
7978 // reject offload during card offline to allow
7979 // fallback to s/w paths
7980 if (offline) {
7981 ret = -ENODEV;
7982 goto error_open;
7983 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007984
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007985 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7986 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7987 ALOGE("%s: Unsupported Offload information", __func__);
7988 ret = -EINVAL;
7989 goto error_open;
7990 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007991
Atul Khare3fa6e542017-08-09 00:56:17 +05307992 if (config->offload_info.format == 0)
7993 config->offload_info.format = config->format;
7994 if (config->offload_info.sample_rate == 0)
7995 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007996
Mingming Yin90310102013-11-13 16:57:00 -08007997 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307998 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007999 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008000 ret = -EINVAL;
8001 goto error_open;
8002 }
8003
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008004 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8005 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8006 (audio_extn_passthru_is_passthrough_stream(out)) &&
8007 !((config->sample_rate == 48000) ||
8008 (config->sample_rate == 96000) ||
8009 (config->sample_rate == 192000))) {
8010 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8011 __func__, config->sample_rate, config->offload_info.format);
8012 ret = -EINVAL;
8013 goto error_open;
8014 }
8015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008016 out->compr_config.codec = (struct snd_codec *)
8017 calloc(1, sizeof(struct snd_codec));
8018
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008019 if (!out->compr_config.codec) {
8020 ret = -ENOMEM;
8021 goto error_open;
8022 }
8023
Dhananjay Kumarac341582017-02-23 23:42:25 +05308024 out->stream.pause = out_pause;
8025 out->stream.resume = out_resume;
8026 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308027 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308028 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008029 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308030 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008031 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308032 } else {
8033 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8034 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008035 }
vivek mehta446c3962015-09-14 10:57:35 -07008036
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308037 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8038 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008039#ifdef AUDIO_GKI_ENABLED
8040 /* out->compr_config.codec->reserved[1] is for flags */
8041 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8042#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308043 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008044#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308045 }
8046
vivek mehta446c3962015-09-14 10:57:35 -07008047 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008048 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008049 config->format == 0 && config->sample_rate == 0 &&
8050 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008051 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008052 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8053 } else {
8054 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8055 ret = -EEXIST;
8056 goto error_open;
8057 }
vivek mehta446c3962015-09-14 10:57:35 -07008058 }
8059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008060 if (config->offload_info.channel_mask)
8061 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008062 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008063 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008064 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008065 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308066 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008067 ret = -EINVAL;
8068 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008069 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008070
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008071 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008072 out->sample_rate = config->offload_info.sample_rate;
8073
Mingming Yin3ee55c62014-08-04 14:23:35 -07008074 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008075
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308076 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308077 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308078 audio_extn_dolby_send_ddp_endp_params(adev);
8079 audio_extn_dolby_set_dmid(adev);
8080 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008082 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008083 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008084 out->compr_config.codec->bit_rate =
8085 config->offload_info.bit_rate;
8086 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308087 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008088 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308089 /* Update bit width only for non passthrough usecases.
8090 * For passthrough usecases, the output will always be opened @16 bit
8091 */
8092 if (!audio_extn_passthru_is_passthrough_stream(out))
8093 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308094
8095 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008096#ifdef AUDIO_GKI_ENABLED
8097 /* out->compr_config.codec->reserved[1] is for flags */
8098 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8099 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8100#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308101 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8102 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008103#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308104
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008105 /*TODO: Do we need to change it for passthrough */
8106 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008107
Manish Dewangana6fc5442015-08-24 20:30:31 +05308108 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8109 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308110 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308111 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308112 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8113 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308114
8115 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8116 AUDIO_FORMAT_PCM) {
8117
8118 /*Based on platform support, configure appropriate alsa format for corresponding
8119 *hal input format.
8120 */
8121 out->compr_config.codec->format = hal_format_to_alsa(
8122 config->offload_info.format);
8123
Ashish Jain83a6cc22016-06-28 14:34:17 +05308124 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308125 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308126 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308127
Dhananjay Kumarac341582017-02-23 23:42:25 +05308128 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308129 *hal input format and alsa format might differ based on platform support.
8130 */
8131 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308132 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308133
8134 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8135
Deeraj Soman93155a62019-09-30 19:00:37 +05308136 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8137 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8138 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8139 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8140 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308141
Ashish Jainf1eaa582016-05-23 20:54:24 +05308142 /* Check if alsa session is configured with the same format as HAL input format,
8143 * if not then derive correct fragment size needed to accomodate the
8144 * conversion of HAL input format to alsa format.
8145 */
8146 audio_extn_utils_update_direct_pcm_fragment_size(out);
8147
8148 /*if hal input and output fragment size is different this indicates HAL input format is
8149 *not same as the alsa format
8150 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308151 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308152 /*Allocate a buffer to convert input data to the alsa configured format.
8153 *size of convert buffer is equal to the size required to hold one fragment size
8154 *worth of pcm data, this is because flinger does not write more than fragment_size
8155 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308156 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8157 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308158 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8159 ret = -ENOMEM;
8160 goto error_open;
8161 }
8162 }
8163 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8164 out->compr_config.fragment_size =
8165 audio_extn_passthru_get_buffer_size(&config->offload_info);
8166 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8167 } else {
8168 out->compr_config.fragment_size =
8169 platform_get_compress_offload_buffer_size(&config->offload_info);
8170 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8171 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008172
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308173 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8174 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8175 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008176 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8177#ifdef AUDIO_GKI_ENABLED
8178 generic_dec =
8179 &(out->compr_config.codec->options.generic.reserved[1]);
8180 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8181 AUDIO_OUTPUT_BIT_WIDTH;
8182#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308183 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008184#endif
8185 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008186
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308187 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8188 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8189 }
8190
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008191 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8192 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008193
Manish Dewangan69426c82017-01-30 17:35:36 +05308194 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8195 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8196 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8197 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8198 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8199 } else {
8200 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8201 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008202
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308203 memset(&out->channel_map_param, 0,
8204 sizeof(struct audio_out_channel_map_param));
8205
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008206 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308207 out->send_next_track_params = false;
8208 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008209 out->offload_state = OFFLOAD_STATE_IDLE;
8210 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008211 out->writeAt.tv_sec = 0;
8212 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008213
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008214 audio_extn_dts_create_state_notifier_node(out->usecase);
8215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008216 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8217 __func__, config->offload_info.version,
8218 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308219
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308220 /* Check if DSD audio format is supported in codec
8221 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308222 */
8223
8224 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308225 (!platform_check_codec_dsd_support(adev->platform) ||
8226 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308227 ret = -EINVAL;
8228 goto error_open;
8229 }
8230
Ashish Jain5106d362016-05-11 19:23:33 +05308231 /* Disable gapless if any of the following is true
8232 * passthrough playback
8233 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308234 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308235 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308236 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308237 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008238 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308239 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308240 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308241 check_and_set_gapless_mode(adev, false);
8242 } else
8243 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008244
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308245 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008246 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8247 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308248 if (config->format == AUDIO_FORMAT_DSD) {
8249 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008250#ifdef AUDIO_GKI_ENABLED
8251 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8252 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8253#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308254 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008255#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308256 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008257
8258 create_offload_callback_thread(out);
8259
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008260 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008261 switch (config->sample_rate) {
8262 case 0:
8263 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8264 break;
8265 case 8000:
8266 case 16000:
8267 case 48000:
8268 out->sample_rate = config->sample_rate;
8269 break;
8270 default:
8271 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8272 config->sample_rate);
8273 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8274 ret = -EINVAL;
8275 goto error_open;
8276 }
8277 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8278 switch (config->channel_mask) {
8279 case AUDIO_CHANNEL_NONE:
8280 case AUDIO_CHANNEL_OUT_STEREO:
8281 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8282 break;
8283 default:
8284 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8285 config->channel_mask);
8286 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8287 ret = -EINVAL;
8288 goto error_open;
8289 }
8290 switch (config->format) {
8291 case AUDIO_FORMAT_DEFAULT:
8292 case AUDIO_FORMAT_PCM_16_BIT:
8293 out->format = AUDIO_FORMAT_PCM_16_BIT;
8294 break;
8295 default:
8296 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8297 config->format);
8298 config->format = AUDIO_FORMAT_PCM_16_BIT;
8299 ret = -EINVAL;
8300 goto error_open;
8301 }
8302
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308303 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008304 if (ret != 0) {
8305 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008306 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008307 goto error_open;
8308 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008309 } else if (is_single_device_type_equal(&out->device_list,
8310 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008311 switch (config->sample_rate) {
8312 case 0:
8313 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8314 break;
8315 case 8000:
8316 case 16000:
8317 case 48000:
8318 out->sample_rate = config->sample_rate;
8319 break;
8320 default:
8321 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8322 config->sample_rate);
8323 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8324 ret = -EINVAL;
8325 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008326 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008327 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8328 switch (config->channel_mask) {
8329 case AUDIO_CHANNEL_NONE:
8330 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8331 break;
8332 case AUDIO_CHANNEL_OUT_STEREO:
8333 out->channel_mask = config->channel_mask;
8334 break;
8335 default:
8336 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8337 config->channel_mask);
8338 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8339 ret = -EINVAL;
8340 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008341 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008342 switch (config->format) {
8343 case AUDIO_FORMAT_DEFAULT:
8344 out->format = AUDIO_FORMAT_PCM_16_BIT;
8345 break;
8346 case AUDIO_FORMAT_PCM_16_BIT:
8347 out->format = config->format;
8348 break;
8349 default:
8350 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8351 config->format);
8352 config->format = AUDIO_FORMAT_PCM_16_BIT;
8353 ret = -EINVAL;
8354 break;
8355 }
8356 if (ret != 0)
8357 goto error_open;
8358
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008359 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8360 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008361 out->config.rate = out->sample_rate;
8362 out->config.channels =
8363 audio_channel_count_from_out_mask(out->channel_mask);
8364 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008365 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008366 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308367 unsigned int channels = 0;
8368 /*Update config params to default if not set by the caller*/
8369 if (config->sample_rate == 0)
8370 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8371 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8372 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8373 if (config->format == AUDIO_FORMAT_DEFAULT)
8374 config->format = AUDIO_FORMAT_PCM_16_BIT;
8375
8376 channels = audio_channel_count_from_out_mask(out->channel_mask);
8377
Varun Balaraje49253e2017-07-06 19:48:56 +05308378 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8379 out->usecase = get_interactive_usecase(adev);
8380 out->config = pcm_config_low_latency;
8381 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308382 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008383 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8384 out->flags);
8385 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008386 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8387 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8388 out->config = pcm_config_mmap_playback;
8389 out->stream.start = out_start;
8390 out->stream.stop = out_stop;
8391 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8392 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308393 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8394 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008395 out->hal_output_suspend_supported =
8396 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8397 out->dynamic_pm_qos_config_supported =
8398 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8399 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008400 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8401 } else {
8402 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8403 //the mixer path will be a string similar to "low-latency-playback resume"
8404 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8405 strlcat(out->pm_qos_mixer_path,
8406 " resume", MAX_MIXER_PATH_LEN);
8407 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8408 out->pm_qos_mixer_path);
8409 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308410 out->config = pcm_config_low_latency;
8411 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8412 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8413 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308414 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8415 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8416 if (out->config.period_size <= 0) {
8417 ALOGE("Invalid configuration period size is not valid");
8418 ret = -EINVAL;
8419 goto error_open;
8420 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008421 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8422 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8423 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008424 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8425 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8426 out->config = pcm_config_haptics_audio;
8427 if (force_haptic_path)
8428 adev->haptics_config = pcm_config_haptics_audio;
8429 else
8430 adev->haptics_config = pcm_config_haptics;
8431
Meng Wangd08ce322020-04-02 08:59:20 +08008432 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008433 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8434
8435 if (force_haptic_path) {
8436 out->config.channels = 1;
8437 adev->haptics_config.channels = 1;
8438 } else
8439 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 -08008440 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008441 ret = audio_extn_auto_hal_open_output_stream(out);
8442 if (ret) {
8443 ALOGE("%s: Failed to open output stream for bus device", __func__);
8444 ret = -EINVAL;
8445 goto error_open;
8446 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308447 } else {
8448 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008449 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8450 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308451 }
8452 out->hal_ip_format = format = out->format;
8453 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8454 out->hal_op_format = pcm_format_to_hal(out->config.format);
8455 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8456 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008457 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308458 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308459 if (out->hal_ip_format != out->hal_op_format) {
8460 uint32_t buffer_size = out->config.period_size *
8461 format_to_bitwidth_table[out->hal_op_format] *
8462 out->config.channels;
8463 out->convert_buffer = calloc(1, buffer_size);
8464 if (out->convert_buffer == NULL){
8465 ALOGE("Allocation failed for convert buffer for size %d",
8466 out->compr_config.fragment_size);
8467 ret = -ENOMEM;
8468 goto error_open;
8469 }
8470 ALOGD("Convert buffer allocated of size %d", buffer_size);
8471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008472 }
8473
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008474 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8475 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308476
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008477 /* TODO remove this hardcoding and check why width is zero*/
8478 if (out->bit_width == 0)
8479 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308480 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008481 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008482 &out->device_list, out->flags,
8483 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308484 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308485 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008486 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008487 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8488 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008489 if(adev->primary_output == NULL)
8490 adev->primary_output = out;
8491 else {
8492 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008493 ret = -EEXIST;
8494 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008495 }
8496 }
8497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498 /* Check if this usecase is already existing */
8499 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008500 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8501 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008502 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008503 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008504 ret = -EEXIST;
8505 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008508 pthread_mutex_unlock(&adev->lock);
8509
8510 out->stream.common.get_sample_rate = out_get_sample_rate;
8511 out->stream.common.set_sample_rate = out_set_sample_rate;
8512 out->stream.common.get_buffer_size = out_get_buffer_size;
8513 out->stream.common.get_channels = out_get_channels;
8514 out->stream.common.get_format = out_get_format;
8515 out->stream.common.set_format = out_set_format;
8516 out->stream.common.standby = out_standby;
8517 out->stream.common.dump = out_dump;
8518 out->stream.common.set_parameters = out_set_parameters;
8519 out->stream.common.get_parameters = out_get_parameters;
8520 out->stream.common.add_audio_effect = out_add_audio_effect;
8521 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8522 out->stream.get_latency = out_get_latency;
8523 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008524#ifdef NO_AUDIO_OUT
8525 out->stream.write = out_write_for_no_output;
8526#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008527 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008528#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529 out->stream.get_render_position = out_get_render_position;
8530 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008531 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008532
Haynes Mathew George16081042017-05-31 17:16:49 -07008533 if (out->realtime)
8534 out->af_period_multiplier = af_period_multiplier;
8535 else
8536 out->af_period_multiplier = 1;
8537
Andy Hunga1f48fa2019-07-01 18:14:53 -07008538 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008540 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008541 out->volume_l = PLAYBACK_GAIN_MAX;
8542 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008543 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008544 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008545
8546 config->format = out->stream.common.get_format(&out->stream.common);
8547 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8548 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308549 register_format(out->format, out->supported_formats);
8550 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8551 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552
Aalique Grahame22e49102018-12-18 14:23:57 -08008553 out->error_log = error_log_create(
8554 ERROR_LOG_ENTRIES,
8555 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8556
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308557 /*
8558 By locking output stream before registering, we allow the callback
8559 to update stream's state only after stream's initial state is set to
8560 adev state.
8561 */
8562 lock_output_stream(out);
8563 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8564 pthread_mutex_lock(&adev->lock);
8565 out->card_status = adev->card_status;
8566 pthread_mutex_unlock(&adev->lock);
8567 pthread_mutex_unlock(&out->lock);
8568
Aalique Grahame22e49102018-12-18 14:23:57 -08008569 stream_app_type_cfg_init(&out->app_type_cfg);
8570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008571 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308572 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008573 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008574
8575 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8576 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8577 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008578 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308579 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008580 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008581 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308582 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8583 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008584 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8585 out->usecase, PCM_PLAYBACK);
8586 hdlr_stream_cfg.flags = out->flags;
8587 hdlr_stream_cfg.type = PCM_PLAYBACK;
8588 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8589 &hdlr_stream_cfg);
8590 if (ret) {
8591 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8592 out->adsp_hdlr_stream_handle = NULL;
8593 }
8594 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308595 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8596 is_direct_passthough, false);
8597 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8598 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008599 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008600 if (ret < 0) {
8601 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8602 out->ip_hdlr_handle = NULL;
8603 }
8604 }
Derek Chenf939fb72018-11-13 13:34:41 -08008605
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008606 ret = io_streams_map_insert(adev, &out->stream.common,
8607 out->handle, AUDIO_PATCH_HANDLE_NONE);
8608 if (ret != 0)
8609 goto error_open;
8610
Susan Wang6dd13092021-01-25 10:27:11 -05008611 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008612
8613 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008614 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008615 pthread_mutex_unlock(&adev->lock);
8616
Eric Laurent994a6932013-07-17 11:51:42 -07008617 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008618 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008619
8620error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308621 if (out->convert_buffer)
8622 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008623 free(out);
8624 *stream_out = NULL;
8625 ALOGD("%s: exit: ret %d", __func__, ret);
8626 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008627}
8628
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308629void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008630 struct audio_stream_out *stream)
8631{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008632 struct stream_out *out = (struct stream_out *)stream;
8633 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008634 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008635
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008636 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308637
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008638 io_streams_map_remove(adev, out->handle);
8639
Susan Wang6dd13092021-01-25 10:27:11 -05008640 // remove out_ctxt early to prevent the stream
8641 // being opened in a race condition
8642 pthread_mutex_lock(&adev->lock);
8643 list_remove(&out->out_ctxt.list);
8644 pthread_mutex_unlock(&adev->lock);
8645
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308646 // must deregister from sndmonitor first to prevent races
8647 // between the callback and close_stream
8648 audio_extn_snd_mon_unregister_listener(out);
8649
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008650 /* close adsp hdrl session before standby */
8651 if (out->adsp_hdlr_stream_handle) {
8652 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8653 if (ret)
8654 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8655 out->adsp_hdlr_stream_handle = NULL;
8656 }
8657
Manish Dewangan21a850a2017-08-14 12:03:55 +05308658 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008659 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8660 out->ip_hdlr_handle = NULL;
8661 }
8662
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008663 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308664 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008665 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308666 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308667 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008668 if(ret != 0)
8669 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8670 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008671 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008672 out_standby(&stream->common);
8673
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008674 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008675 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008676 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008677 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008678 if (out->compr_config.codec != NULL)
8679 free(out->compr_config.codec);
8680 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008681
Zhou Songbaddf9f2020-11-20 13:57:39 +08008682 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308683
Varun Balaraje49253e2017-07-06 19:48:56 +05308684 if (is_interactive_usecase(out->usecase))
8685 free_interactive_usecase(adev, out->usecase);
8686
Ashish Jain83a6cc22016-06-28 14:34:17 +05308687 if (out->convert_buffer != NULL) {
8688 free(out->convert_buffer);
8689 out->convert_buffer = NULL;
8690 }
8691
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008692 if (adev->voice_tx_output == out)
8693 adev->voice_tx_output = NULL;
8694
Aalique Grahame22e49102018-12-18 14:23:57 -08008695 error_log_destroy(out->error_log);
8696 out->error_log = NULL;
8697
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308698 if (adev->primary_output == out)
8699 adev->primary_output = NULL;
8700
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008701 pthread_cond_destroy(&out->cond);
8702 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008703 pthread_mutex_destroy(&out->pre_lock);
8704 pthread_mutex_destroy(&out->latch_lock);
8705 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008706
8707 pthread_mutex_lock(&adev->lock);
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
Weiyin Jiang24f55292020-12-22 14:35:46 +08008734 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8735 if (ret >= 0) {
8736 list_for_each(node, &adev->active_outputs_list) {
8737 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8738 streams_output_ctxt_t,
8739 list);
8740 out_snd_mon_cb((void *)out_ctxt->output, parms);
8741 }
Derek Chen6f293672019-04-01 01:40:24 -07008742
Weiyin Jiang24f55292020-12-22 14:35:46 +08008743 list_for_each(node, &adev->active_inputs_list) {
8744 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8745 streams_input_ctxt_t,
8746 list);
8747 in_snd_mon_cb((void *)in_ctxt->input, parms);
8748 }
Derek Chen6f293672019-04-01 01:40:24 -07008749 }
8750
Zhou Songd6d71752019-05-21 18:08:51 +08008751 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308752 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8753 if (ret >= 0) {
8754 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008755 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308756 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308757 /*
8758 * When ever BT_SCO=ON arrives, make sure to route
8759 * all use cases to SCO device, otherwise due to delay in
8760 * BT_SCO=ON and lack of synchronization with create audio patch
8761 * request for SCO device, some times use case not routed properly to
8762 * SCO device
8763 */
8764 struct audio_usecase *usecase;
8765 struct listnode *node;
8766 list_for_each(node, &adev->usecase_list) {
8767 usecase = node_to_item(node, struct audio_usecase, list);
8768 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
8769 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device))) {
8770 ALOGD("BT_SCO ON, switch all in use case to it");
8771 select_devices(adev, usecase->id);
8772 }
8773 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
8774 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE))) {
8775 ALOGD("BT_SCO ON, switch all out use case to it");
8776 select_devices(adev, usecase->id);
8777 }
8778 }
8779 }
8780 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308781 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008782 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008783 }
8784 }
8785
8786 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008787 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008788 if (!strncmp(value, "false", 5) &&
8789 audio_extn_a2dp_source_is_suspended()) {
8790 struct audio_usecase *usecase;
8791 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008792 list_for_each(node, &adev->usecase_list) {
8793 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008794 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008795 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008796 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008797 reassign_device_list(&usecase->stream.in->device_list,
8798 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008799 select_devices(adev, usecase->id);
8800 }
Zhou Songd6d71752019-05-21 18:08:51 +08008801 }
8802 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308803 }
8804
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008805 status = voice_set_parameters(adev, parms);
8806 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008807 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008808
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008809 status = platform_set_parameters(adev->platform, parms);
8810 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008811 goto done;
8812
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008813 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8814 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008815 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008816 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8817 adev->bluetooth_nrec = true;
8818 else
8819 adev->bluetooth_nrec = false;
8820 }
8821
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008822 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8823 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8825 adev->screen_off = false;
8826 else
8827 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008828 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008829 }
8830
Eric Laurent4b084132018-10-19 17:33:43 -07008831 ret = str_parms_get_int(parms, "rotation", &val);
8832 if (ret >= 0) {
8833 bool reverse_speakers = false;
8834 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8835 switch (val) {
8836 // FIXME: note that the code below assumes that the speakers are in the correct placement
8837 // relative to the user when the device is rotated 90deg from its default rotation. This
8838 // assumption is device-specific, not platform-specific like this code.
8839 case 270:
8840 reverse_speakers = true;
8841 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8842 break;
8843 case 0:
8844 case 180:
8845 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8846 break;
8847 case 90:
8848 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8849 break;
8850 default:
8851 ALOGE("%s: unexpected rotation of %d", __func__, val);
8852 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008853 }
Eric Laurent4b084132018-10-19 17:33:43 -07008854 if (status == 0) {
8855 // check and set swap
8856 // - check if orientation changed and speaker active
8857 // - set rotation and cache the rotation value
8858 adev->camera_orientation =
8859 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8860 if (!audio_extn_is_maxx_audio_enabled())
8861 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8862 }
8863 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008864
Mingming Yin514a8bc2014-07-29 15:22:21 -07008865 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8866 if (ret >= 0) {
8867 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8868 adev->bt_wb_speech_enabled = true;
8869 else
8870 adev->bt_wb_speech_enabled = false;
8871 }
8872
Zhou Song12c29502019-03-16 10:37:18 +08008873 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8874 if (ret >= 0) {
8875 val = atoi(value);
8876 adev->swb_speech_mode = val;
8877 }
8878
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008879 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8880 if (ret >= 0) {
8881 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308882 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008883 if (audio_is_output_device(val) &&
8884 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008885 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008886 platform_get_controller_stream_from_params(parms, &controller, &stream);
8887 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8888 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008889 if (ret < 0) {
8890 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308891 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008892 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008893 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308894 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008895 /*
8896 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8897 * Per AudioPolicyManager, USB device is higher priority than WFD.
8898 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8899 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8900 * starting voice call on USB
8901 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008902 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308903 if (ret >= 0)
8904 audio_extn_usb_add_device(device, atoi(value));
8905
Zhou Song6f862822017-11-06 17:27:57 +08008906 if (!audio_extn_usb_is_tunnel_supported()) {
8907 ALOGV("detected USB connect .. disable proxy");
8908 adev->allow_afe_proxy_usage = false;
8909 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008910 }
8911 }
8912
8913 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8914 if (ret >= 0) {
8915 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308916 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008917 /*
8918 * The HDMI / Displayport disconnect handling has been moved to
8919 * audio extension to ensure that its parameters are not
8920 * invalidated prior to updating sysfs of the disconnect event
8921 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8922 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308923 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008924 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308925 if (ret >= 0)
8926 audio_extn_usb_remove_device(device, atoi(value));
8927
Zhou Song6f862822017-11-06 17:27:57 +08008928 if (!audio_extn_usb_is_tunnel_supported()) {
8929 ALOGV("detected USB disconnect .. enable proxy");
8930 adev->allow_afe_proxy_usage = true;
8931 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008932 }
8933 }
8934
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008935 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008936
8937 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008938 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308939 struct audio_usecase *usecase;
8940 struct listnode *node;
8941 list_for_each(node, &adev->usecase_list) {
8942 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008943 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8944 continue;
8945
8946 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308947 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308948 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308949 ALOGD("Switching to speaker and muting the stream before select_devices");
8950 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308951 //force device switch to re configure encoder
8952 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308953 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08008954 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308955 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308956 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008957 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008958 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08008959 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008960 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8961 reassign_device_list(&usecase->stream.out->device_list,
8962 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8963 check_a2dp_restore_l(adev, usecase->stream.out, true);
8964 break;
8965 }
8966 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308967 }
8968 }
8969 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008970
8971 //handle vr audio setparam
8972 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8973 value, sizeof(value));
8974 if (ret >= 0) {
8975 ALOGI("Setting vr mode to be %s", value);
8976 if (!strncmp(value, "true", 4)) {
8977 adev->vr_audio_mode_enabled = true;
8978 ALOGI("Setting vr mode to true");
8979 } else if (!strncmp(value, "false", 5)) {
8980 adev->vr_audio_mode_enabled = false;
8981 ALOGI("Setting vr mode to false");
8982 } else {
8983 ALOGI("wrong vr mode set");
8984 }
8985 }
8986
Eric Laurent4b084132018-10-19 17:33:43 -07008987 //FIXME: to be replaced by proper video capture properties API
8988 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8989 if (ret >= 0) {
8990 int camera_facing = CAMERA_FACING_BACK;
8991 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8992 camera_facing = CAMERA_FACING_FRONT;
8993 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8994 camera_facing = CAMERA_FACING_BACK;
8995 else {
8996 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8997 goto done;
8998 }
8999 adev->camera_orientation =
9000 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9001 struct audio_usecase *usecase;
9002 struct listnode *node;
9003 list_for_each(node, &adev->usecase_list) {
9004 usecase = node_to_item(node, struct audio_usecase, list);
9005 struct stream_in *in = usecase->stream.in;
9006 if (usecase->type == PCM_CAPTURE && in != NULL &&
9007 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9008 select_devices(adev, in->usecase);
9009 }
9010 }
9011 }
9012
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309013 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009014done:
9015 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009016 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309017error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009018 ALOGV("%s: exit with code(%d)", __func__, status);
9019 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009020}
9021
9022static char* adev_get_parameters(const struct audio_hw_device *dev,
9023 const char *keys)
9024{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309025 ALOGD("%s:%s", __func__, keys);
9026
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009027 struct audio_device *adev = (struct audio_device *)dev;
9028 struct str_parms *reply = str_parms_create();
9029 struct str_parms *query = str_parms_create_str(keys);
9030 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309031 char value[256] = {0};
9032 int ret = 0;
9033
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009034 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009035 if (reply) {
9036 str_parms_destroy(reply);
9037 }
9038 if (query) {
9039 str_parms_destroy(query);
9040 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009041 ALOGE("adev_get_parameters: failed to create query or reply");
9042 return NULL;
9043 }
9044
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009045 //handle vr audio getparam
9046
9047 ret = str_parms_get_str(query,
9048 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9049 value, sizeof(value));
9050
9051 if (ret >= 0) {
9052 bool vr_audio_enabled = false;
9053 pthread_mutex_lock(&adev->lock);
9054 vr_audio_enabled = adev->vr_audio_mode_enabled;
9055 pthread_mutex_unlock(&adev->lock);
9056
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009057 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009058
9059 if (vr_audio_enabled) {
9060 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9061 "true");
9062 goto exit;
9063 } else {
9064 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9065 "false");
9066 goto exit;
9067 }
9068 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009069
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009070 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009071 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009072 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009073 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009074 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009075 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309076 pthread_mutex_unlock(&adev->lock);
9077
Naresh Tannirud7205b62014-06-20 02:54:48 +05309078exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009079 str = str_parms_to_str(reply);
9080 str_parms_destroy(query);
9081 str_parms_destroy(reply);
9082
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009083 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009084 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009085}
9086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009087static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009088{
9089 return 0;
9090}
9091
9092static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9093{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009094 int ret;
9095 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009096
9097 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9098
Haynes Mathew George5191a852013-09-11 14:19:36 -07009099 pthread_mutex_lock(&adev->lock);
9100 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009101 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009102 pthread_mutex_unlock(&adev->lock);
9103 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009104}
9105
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009106static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9107 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009108{
9109 return -ENOSYS;
9110}
9111
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009112static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9113 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009114{
9115 return -ENOSYS;
9116}
9117
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009118static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9119 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009120{
9121 return -ENOSYS;
9122}
9123
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009124static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9125 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009126{
9127 return -ENOSYS;
9128}
9129
9130static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9131{
9132 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009133 struct listnode *node;
9134 struct audio_usecase *usecase = NULL;
9135 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009137 pthread_mutex_lock(&adev->lock);
9138 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309139 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9140 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009141 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009142 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309143 adev->current_call_output = adev->primary_output;
9144 voice_start_call(adev);
9145 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009146 (mode == AUDIO_MODE_NORMAL ||
9147 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009148 list_for_each(node, &adev->usecase_list) {
9149 usecase = node_to_item(node, struct audio_usecase, list);
9150 if (usecase->type == VOICE_CALL)
9151 break;
9152 }
9153 if (usecase &&
9154 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9155 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9156 true);
9157 if (ret != 0) {
9158 /* default service interval was successfully updated,
9159 reopen USB backend with new service interval */
9160 check_usecases_codec_backend(adev,
9161 usecase,
9162 usecase->out_snd_device);
9163 }
9164 }
9165
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009166 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009167 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009168 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009169 // restore device for other active usecases after stop call
9170 list_for_each(node, &adev->usecase_list) {
9171 usecase = node_to_item(node, struct audio_usecase, list);
9172 select_devices(adev, usecase->id);
9173 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009175 }
9176 pthread_mutex_unlock(&adev->lock);
9177 return 0;
9178}
9179
9180static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9181{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009182 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009183 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009184
9185 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009186 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009187 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009188
Derek Chend2530072014-11-24 12:39:14 -08009189 if (adev->ext_hw_plugin)
9190 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009191
9192 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009193 pthread_mutex_unlock(&adev->lock);
9194
9195 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009196}
9197
9198static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9199{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009200 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009201 return 0;
9202}
9203
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009204static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009205 const struct audio_config *config)
9206{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009207 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009208
Aalique Grahame22e49102018-12-18 14:23:57 -08009209 /* Don't know if USB HIFI in this context so use true to be conservative */
9210 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9211 true /*is_usb_hifi */) != 0)
9212 return 0;
9213
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009214 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9215 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009216}
9217
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009218static bool adev_input_allow_hifi_record(struct audio_device *adev,
9219 audio_devices_t devices,
9220 audio_input_flags_t flags,
9221 audio_source_t source) {
9222 const bool allowed = true;
9223
9224 if (!audio_is_usb_in_device(devices))
9225 return !allowed;
9226
9227 switch (flags) {
9228 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009229 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009230 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9231 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009232 default:
9233 return !allowed;
9234 }
9235
9236 switch (source) {
9237 case AUDIO_SOURCE_DEFAULT:
9238 case AUDIO_SOURCE_MIC:
9239 case AUDIO_SOURCE_UNPROCESSED:
9240 break;
9241 default:
9242 return !allowed;
9243 }
9244
9245 switch (adev->mode) {
9246 case 0:
9247 break;
9248 default:
9249 return !allowed;
9250 }
9251
9252 return allowed;
9253}
9254
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009255static int adev_update_voice_comm_input_stream(struct stream_in *in,
9256 struct audio_config *config)
9257{
9258 bool valid_rate = (config->sample_rate == 8000 ||
9259 config->sample_rate == 16000 ||
9260 config->sample_rate == 32000 ||
9261 config->sample_rate == 48000);
9262 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9263
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009264 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009265 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009266 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9267 in->config = default_pcm_config_voip_copp;
9268 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9269 DEFAULT_VOIP_BUF_DURATION_MS,
9270 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009271 } else {
9272 ALOGW("%s No valid input in voip, use defaults"
9273 "sample rate %u, channel mask 0x%X",
9274 __func__, config->sample_rate, in->channel_mask);
9275 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009276 in->config.rate = config->sample_rate;
9277 in->sample_rate = config->sample_rate;
9278 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009279 //XXX needed for voice_extn_compress_voip_open_input_stream
9280 in->config.rate = config->sample_rate;
9281 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309282 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009283 voice_extn_compress_voip_is_active(in->dev)) &&
9284 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9285 valid_rate && valid_ch) {
9286 voice_extn_compress_voip_open_input_stream(in);
9287 // update rate entries to match config from AF
9288 in->config.rate = config->sample_rate;
9289 in->sample_rate = config->sample_rate;
9290 } else {
9291 ALOGW("%s compress voip not active, use defaults", __func__);
9292 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009293 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009294 return 0;
9295}
9296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009297static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009298 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009299 audio_devices_t devices,
9300 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009301 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309302 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009303 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009304 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009305{
9306 struct audio_device *adev = (struct audio_device *)dev;
9307 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009308 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009309 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009310 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309311 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009312 bool is_usb_dev = audio_is_usb_in_device(devices);
9313 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9314 devices,
9315 flags,
9316 source);
Andy Hung94320602018-10-29 18:31:12 -07009317 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9318 " sample_rate %u, channel_mask %#x, format %#x",
9319 __func__, flags, is_usb_dev, may_use_hifi_record,
9320 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309321
kunleizdff872d2018-08-20 14:40:33 +08009322 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009323 is_usb_dev = false;
9324 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9325 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9326 __func__, devices);
9327 }
9328
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009329 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009330
9331 if (!(is_usb_dev && may_use_hifi_record)) {
9332 if (config->sample_rate == 0)
9333 config->sample_rate = 48000;
9334 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9335 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9336 if (config->format == AUDIO_FORMAT_DEFAULT)
9337 config->format = AUDIO_FORMAT_PCM_16_BIT;
9338
9339 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9340
Aalique Grahame22e49102018-12-18 14:23:57 -08009341 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9342 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009343 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009345
9346 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009347
9348 if (!in) {
9349 ALOGE("failed to allocate input stream");
9350 return -ENOMEM;
9351 }
9352
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309353 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309354 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9355 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009356 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009357 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009359 in->stream.common.get_sample_rate = in_get_sample_rate;
9360 in->stream.common.set_sample_rate = in_set_sample_rate;
9361 in->stream.common.get_buffer_size = in_get_buffer_size;
9362 in->stream.common.get_channels = in_get_channels;
9363 in->stream.common.get_format = in_get_format;
9364 in->stream.common.set_format = in_set_format;
9365 in->stream.common.standby = in_standby;
9366 in->stream.common.dump = in_dump;
9367 in->stream.common.set_parameters = in_set_parameters;
9368 in->stream.common.get_parameters = in_get_parameters;
9369 in->stream.common.add_audio_effect = in_add_audio_effect;
9370 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9371 in->stream.set_gain = in_set_gain;
9372 in->stream.read = in_read;
9373 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009374 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309375 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009376 in->stream.set_microphone_direction = in_set_microphone_direction;
9377 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009378 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009379
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009380 list_init(&in->device_list);
9381 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009382 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009383 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009384 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009385 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009386 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009387 in->bit_width = 16;
9388 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009389 in->direction = MIC_DIRECTION_UNSPECIFIED;
9390 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009391 list_init(&in->aec_list);
9392 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009393 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009394
Andy Hung94320602018-10-29 18:31:12 -07009395 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009396 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9397 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9398 /* Force channel config requested to mono if incall
9399 record is being requested for only uplink/downlink */
9400 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9401 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9402 ret = -EINVAL;
9403 goto err_open;
9404 }
9405 }
9406
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009407 if (is_usb_dev && may_use_hifi_record) {
9408 /* HiFi record selects an appropriate format, channel, rate combo
9409 depending on sink capabilities*/
9410 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9411 &config->format,
9412 &in->supported_formats[0],
9413 MAX_SUPPORTED_FORMATS,
9414 &config->channel_mask,
9415 &in->supported_channel_masks[0],
9416 MAX_SUPPORTED_CHANNEL_MASKS,
9417 &config->sample_rate,
9418 &in->supported_sample_rates[0],
9419 MAX_SUPPORTED_SAMPLE_RATES);
9420 if (ret != 0) {
9421 ret = -EINVAL;
9422 goto err_open;
9423 }
9424 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009425 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309426 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309427 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9428 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9429 in->config.format = PCM_FORMAT_S32_LE;
9430 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309431 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9432 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9433 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9434 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9435 bool ret_error = false;
9436 in->bit_width = 24;
9437 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9438 from HAL is 24_packed and 8_24
9439 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9440 24_packed return error indicating supported format is 24_packed
9441 *> In case of any other source requesting 24 bit or float return error
9442 indicating format supported is 16 bit only.
9443
9444 on error flinger will retry with supported format passed
9445 */
9446 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9447 (source != AUDIO_SOURCE_CAMCORDER)) {
9448 config->format = AUDIO_FORMAT_PCM_16_BIT;
9449 if (config->sample_rate > 48000)
9450 config->sample_rate = 48000;
9451 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009452 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9453 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309454 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9455 ret_error = true;
9456 }
9457
9458 if (ret_error) {
9459 ret = -EINVAL;
9460 goto err_open;
9461 }
9462 }
9463
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009464 in->channel_mask = config->channel_mask;
9465 in->format = config->format;
9466
9467 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309468
Huicheng Liu1404ba12020-09-11 01:03:25 -04009469 /* validate bus device address */
9470 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9471 /* extract car audio stream index */
9472 in->car_audio_stream =
9473 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9474 if (in->car_audio_stream < 0) {
9475 ALOGE("%s: invalid car audio stream %x",
9476 __func__, in->car_audio_stream);
9477 ret = -EINVAL;
9478 goto err_open;
9479 }
9480 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009481 ret = audio_extn_auto_hal_open_input_stream(in);
9482 if (ret) {
9483 ALOGE("%s: Failed to open input stream for bus device", __func__);
9484 ret = -EINVAL;
9485 goto err_open;
9486 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009487 }
9488
Susan Wange3959562021-03-11 11:50:26 -05009489 /* reassign use case for echo reference stream on automotive platforms */
9490 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9491 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9492 }
9493
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309494 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9495 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9496 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9497 else {
9498 ret = -EINVAL;
9499 goto err_open;
9500 }
9501 }
9502
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009503 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309504 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9505 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009506 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9507 is_low_latency = true;
9508#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309509 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9510 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9511 else
9512 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009513#endif
9514 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009515 if (!in->realtime) {
9516 in->config = pcm_config_audio_capture;
9517 frame_size = audio_stream_in_frame_size(&in->stream);
9518 buffer_size = get_input_buffer_size(config->sample_rate,
9519 config->format,
9520 channel_count,
9521 is_low_latency);
9522 in->config.period_size = buffer_size / frame_size;
9523 in->config.rate = config->sample_rate;
9524 in->af_period_multiplier = 1;
9525 } else {
9526 // period size is left untouched for rt mode playback
9527 in->config = pcm_config_audio_capture_rt;
9528 in->af_period_multiplier = af_period_multiplier;
9529 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009530 }
9531
9532 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9533 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9534 in->realtime = 0;
9535 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9536 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009537 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009538 in->stream.start = in_start;
9539 in->stream.stop = in_stop;
9540 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9541 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009542 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009543 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009544 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9545 in->config = pcm_config_audio_capture;
9546 frame_size = audio_stream_in_frame_size(&in->stream);
9547 buffer_size = get_input_buffer_size(config->sample_rate,
9548 config->format,
9549 channel_count,
9550 false /*is_low_latency*/);
9551 in->config.period_size = buffer_size / frame_size;
9552 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009553 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009554 switch (config->format) {
9555 case AUDIO_FORMAT_PCM_32_BIT:
9556 in->bit_width = 32;
9557 break;
9558 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9559 case AUDIO_FORMAT_PCM_8_24_BIT:
9560 in->bit_width = 24;
9561 break;
9562 default:
9563 in->bit_width = 16;
9564 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009565 } else if (is_single_device_type_equal(&in->device_list,
9566 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9567 is_single_device_type_equal(&in->device_list,
9568 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009569 if (config->sample_rate == 0)
9570 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9571 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9572 config->sample_rate != 8000) {
9573 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9574 ret = -EINVAL;
9575 goto err_open;
9576 }
9577 if (config->format == AUDIO_FORMAT_DEFAULT)
9578 config->format = AUDIO_FORMAT_PCM_16_BIT;
9579 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9580 config->format = AUDIO_FORMAT_PCM_16_BIT;
9581 ret = -EINVAL;
9582 goto err_open;
9583 }
9584
9585 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009586 if (adev->ha_proxy_enable &&
9587 is_single_device_type_equal(&in->device_list,
9588 AUDIO_DEVICE_IN_TELEPHONY_RX))
9589 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009590 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009591 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009592 in->af_period_multiplier = 1;
9593 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309594 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009595 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9596 (config->sample_rate == 8000 ||
9597 config->sample_rate == 16000 ||
9598 config->sample_rate == 32000 ||
9599 config->sample_rate == 48000) &&
9600 channel_count == 1) {
9601 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9602 in->config = pcm_config_audio_capture;
9603 frame_size = audio_stream_in_frame_size(&in->stream);
9604 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9605 config->sample_rate,
9606 config->format,
9607 channel_count, false /*is_low_latency*/);
9608 in->config.period_size = buffer_size / frame_size;
9609 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9610 in->config.rate = config->sample_rate;
9611 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009612 } else if (in->realtime) {
9613 in->config = pcm_config_audio_capture_rt;
9614 in->config.format = pcm_format_from_audio_format(config->format);
9615 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009616 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309617 int ret_val;
9618 pthread_mutex_lock(&adev->lock);
9619 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9620 in, config, &channel_mask_updated);
9621 pthread_mutex_unlock(&adev->lock);
9622
9623 if (!ret_val) {
9624 if (channel_mask_updated == true) {
9625 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9626 __func__, config->channel_mask);
9627 ret = -EINVAL;
9628 goto err_open;
9629 }
9630 ALOGD("%s: created multi-channel session succesfully",__func__);
9631 } else if (audio_extn_compr_cap_enabled() &&
9632 audio_extn_compr_cap_format_supported(config->format) &&
9633 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9634 audio_extn_compr_cap_init(in);
9635 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309636 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309637 if (ret)
9638 goto err_open;
9639 } else {
9640 in->config = pcm_config_audio_capture;
9641 in->config.rate = config->sample_rate;
9642 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309643 in->format = config->format;
9644 frame_size = audio_stream_in_frame_size(&in->stream);
9645 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009646 config->format,
9647 channel_count,
9648 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009649 /* prevent division-by-zero */
9650 if (frame_size == 0) {
9651 ALOGE("%s: Error frame_size==0", __func__);
9652 ret = -EINVAL;
9653 goto err_open;
9654 }
9655
Revathi Uddarajud2634032017-12-07 14:42:34 +05309656 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009657 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009658
Revathi Uddarajud2634032017-12-07 14:42:34 +05309659 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9660 /* optionally use VOIP usecase depending on config(s) */
9661 ret = adev_update_voice_comm_input_stream(in, config);
9662 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009663
Revathi Uddarajud2634032017-12-07 14:42:34 +05309664 if (ret) {
9665 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9666 goto err_open;
9667 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009668 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309669
9670 /* assign concurrent capture usecase if record has to caried out from
9671 * actual hardware input source */
9672 if (audio_extn_is_concurrent_capture_enabled() &&
9673 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309674 /* Acquire lock to avoid two concurrent use cases initialized to
9675 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009676
Samyak Jainc37062f2019-04-25 18:41:06 +05309677 if (in->usecase == USECASE_AUDIO_RECORD) {
9678 pthread_mutex_lock(&adev->lock);
9679 if (!(adev->pcm_record_uc_state)) {
9680 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9681 adev->pcm_record_uc_state = 1;
9682 pthread_mutex_unlock(&adev->lock);
9683 } else {
9684 pthread_mutex_unlock(&adev->lock);
9685 /* Assign compress record use case for second record */
9686 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9687 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9688 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9689 if (audio_extn_cin_applicable_stream(in)) {
9690 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309691 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309692 if (ret)
9693 goto err_open;
9694 }
9695 }
9696 }
kunleiz28c73e72019-03-27 17:24:04 +08009697 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009698 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309699 if (audio_extn_ssr_get_stream() != in)
9700 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009701
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009702 in->sample_rate = in->config.rate;
9703
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309704 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9705 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009706 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009707 in->sample_rate, in->bit_width,
9708 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309709 register_format(in->format, in->supported_formats);
9710 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9711 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309712
Aalique Grahame22e49102018-12-18 14:23:57 -08009713 in->error_log = error_log_create(
9714 ERROR_LOG_ENTRIES,
9715 1000000000 /* aggregate consecutive identical errors within one second */);
9716
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009717 /* This stream could be for sound trigger lab,
9718 get sound trigger pcm if present */
9719 audio_extn_sound_trigger_check_and_get_session(in);
9720
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309721 lock_input_stream(in);
9722 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9723 pthread_mutex_lock(&adev->lock);
9724 in->card_status = adev->card_status;
9725 pthread_mutex_unlock(&adev->lock);
9726 pthread_mutex_unlock(&in->lock);
9727
Aalique Grahame22e49102018-12-18 14:23:57 -08009728 stream_app_type_cfg_init(&in->app_type_cfg);
9729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009730 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009731
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009732 ret = io_streams_map_insert(adev, &in->stream.common,
9733 handle, AUDIO_PATCH_HANDLE_NONE);
9734 if (ret != 0)
9735 goto err_open;
9736
Susan Wang6dd13092021-01-25 10:27:11 -05009737 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009738
9739 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009740 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009741 pthread_mutex_unlock(&adev->lock);
9742
Eric Laurent994a6932013-07-17 11:51:42 -07009743 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009744 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009745
9746err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309747 if (in->usecase == USECASE_AUDIO_RECORD) {
9748 pthread_mutex_lock(&adev->lock);
9749 adev->pcm_record_uc_state = 0;
9750 pthread_mutex_unlock(&adev->lock);
9751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009752 free(in);
9753 *stream_in = NULL;
9754 return ret;
9755}
9756
9757static void adev_close_input_stream(struct audio_hw_device *dev,
9758 struct audio_stream_in *stream)
9759{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009760 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009761 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009762 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309763
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309764 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009765
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009766 if (in == NULL) {
9767 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9768 return;
9769 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009770 io_streams_map_remove(adev, in->capture_handle);
9771
Susan Wang6dd13092021-01-25 10:27:11 -05009772 // remove out_ctxt early to prevent the stream
9773 // being opened in a race condition
9774 pthread_mutex_lock(&adev->lock);
9775 list_remove(&in->in_ctxt.list);
9776 pthread_mutex_unlock(&adev->lock);
9777
kunleiz70e57612018-12-28 17:50:23 +08009778 /* must deregister from sndmonitor first to prevent races
9779 * between the callback and close_stream
9780 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309781 audio_extn_snd_mon_unregister_listener(stream);
9782
kunleiz70e57612018-12-28 17:50:23 +08009783 /* Disable echo reference if there are no active input, hfp call
9784 * and sound trigger while closing input stream
9785 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009786 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009787 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009788 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9789 struct listnode out_devices;
9790 list_init(&out_devices);
9791 platform_set_echo_reference(adev, false, &out_devices);
9792 } else
kunleiz70e57612018-12-28 17:50:23 +08009793 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309794
Weiyin Jiang2995f662019-04-17 14:25:12 +08009795 error_log_destroy(in->error_log);
9796 in->error_log = NULL;
9797
Pallavid7c7a272018-01-16 11:22:55 +05309798
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009799 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309800 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009801 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309802 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009803 if (ret != 0)
9804 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9805 __func__, ret);
9806 } else
9807 in_standby(&stream->common);
9808
Weiyin Jiang280ea742020-09-08 20:28:22 +08009809 pthread_mutex_destroy(&in->lock);
9810 pthread_mutex_destroy(&in->pre_lock);
9811
Revathi Uddarajud2634032017-12-07 14:42:34 +05309812 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309813 if (in->usecase == USECASE_AUDIO_RECORD) {
9814 adev->pcm_record_uc_state = 0;
9815 }
9816
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009817 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9818 adev->enable_voicerx = false;
9819 }
9820
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009821 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009822 audio_extn_ssr_deinit();
9823 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009824
Garmond Leunge2433c32017-09-28 21:51:22 -07009825 if (audio_extn_ffv_get_stream() == in) {
9826 audio_extn_ffv_stream_deinit();
9827 }
9828
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309829 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009830 audio_extn_compr_cap_format_supported(in->config.format))
9831 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309832
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309833 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309834 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009835
Mingming Yinfd7607b2016-01-22 12:48:44 -08009836 if (in->is_st_session) {
9837 ALOGV("%s: sound trigger pcm stop lab", __func__);
9838 audio_extn_sound_trigger_stop_lab(in);
9839 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009840 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309841 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009842 return;
9843}
9844
Aalique Grahame22e49102018-12-18 14:23:57 -08009845/* verifies input and output devices and their capabilities.
9846 *
9847 * This verification is required when enabling extended bit-depth or
9848 * sampling rates, as not all qcom products support it.
9849 *
9850 * Suitable for calling only on initialization such as adev_open().
9851 * It fills the audio_device use_case_table[] array.
9852 *
9853 * Has a side-effect that it needs to configure audio routing / devices
9854 * in order to power up the devices and read the device parameters.
9855 * It does not acquire any hw device lock. Should restore the devices
9856 * back to "normal state" upon completion.
9857 */
9858static int adev_verify_devices(struct audio_device *adev)
9859{
9860 /* enumeration is a bit difficult because one really wants to pull
9861 * the use_case, device id, etc from the hidden pcm_device_table[].
9862 * In this case there are the following use cases and device ids.
9863 *
9864 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9865 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9866 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9867 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9868 * [USECASE_AUDIO_RECORD] = {0, 0},
9869 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9870 * [USECASE_VOICE_CALL] = {2, 2},
9871 *
9872 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9873 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9874 */
9875
9876 /* should be the usecases enabled in adev_open_input_stream() */
9877 static const int test_in_usecases[] = {
9878 USECASE_AUDIO_RECORD,
9879 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9880 };
9881 /* should be the usecases enabled in adev_open_output_stream()*/
9882 static const int test_out_usecases[] = {
9883 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9884 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9885 };
9886 static const usecase_type_t usecase_type_by_dir[] = {
9887 PCM_PLAYBACK,
9888 PCM_CAPTURE,
9889 };
9890 static const unsigned flags_by_dir[] = {
9891 PCM_OUT,
9892 PCM_IN,
9893 };
9894
9895 size_t i;
9896 unsigned dir;
9897 const unsigned card_id = adev->snd_card;
9898
9899 for (dir = 0; dir < 2; ++dir) {
9900 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9901 const unsigned flags_dir = flags_by_dir[dir];
9902 const size_t testsize =
9903 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9904 const int *testcases =
9905 dir ? test_in_usecases : test_out_usecases;
9906 const audio_devices_t audio_device =
9907 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9908
9909 for (i = 0; i < testsize; ++i) {
9910 const audio_usecase_t audio_usecase = testcases[i];
9911 int device_id;
9912 struct pcm_params **pparams;
9913 struct stream_out out;
9914 struct stream_in in;
9915 struct audio_usecase uc_info;
9916 int retval;
9917
9918 pparams = &adev->use_case_table[audio_usecase];
9919 pcm_params_free(*pparams); /* can accept null input */
9920 *pparams = NULL;
9921
9922 /* find the device ID for the use case (signed, for error) */
9923 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9924 if (device_id < 0)
9925 continue;
9926
9927 /* prepare structures for device probing */
9928 memset(&uc_info, 0, sizeof(uc_info));
9929 uc_info.id = audio_usecase;
9930 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009931 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009932 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009933 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009934 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009935 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009936 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9937 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009938 }
9939 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009940 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009941 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009942 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009943 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009944 uc_info.in_snd_device = SND_DEVICE_NONE;
9945 uc_info.out_snd_device = SND_DEVICE_NONE;
9946 list_add_tail(&adev->usecase_list, &uc_info.list);
9947
9948 /* select device - similar to start_(in/out)put_stream() */
9949 retval = select_devices(adev, audio_usecase);
9950 if (retval >= 0) {
9951 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9952#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009953 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009954 if (*pparams) {
9955 ALOGV("%s: (%s) card %d device %d", __func__,
9956 dir ? "input" : "output", card_id, device_id);
9957 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9958 } else {
9959 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9960 }
9961#endif
9962 }
9963
9964 /* deselect device - similar to stop_(in/out)put_stream() */
9965 /* 1. Get and set stream specific mixer controls */
9966 retval = disable_audio_route(adev, &uc_info);
9967 /* 2. Disable the rx device */
9968 retval = disable_snd_device(adev,
9969 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9970 list_remove(&uc_info.list);
9971 }
9972 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009973 return 0;
9974}
9975
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009976int update_patch(unsigned int num_sources,
9977 const struct audio_port_config *sources,
9978 unsigned int num_sinks,
9979 const struct audio_port_config *sinks,
9980 audio_patch_handle_t handle,
9981 struct audio_patch_info *p_info,
9982 patch_type_t patch_type, bool new_patch)
9983{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009984 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009985
9986 if (p_info == NULL) {
9987 ALOGE("%s: Invalid patch pointer", __func__);
9988 return -EINVAL;
9989 }
9990
9991 if (new_patch) {
9992 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9993 if (p_info->patch == NULL) {
9994 ALOGE("%s: Could not allocate patch", __func__);
9995 return -ENOMEM;
9996 }
9997 }
9998
9999 p_info->patch->id = handle;
10000 p_info->patch->num_sources = num_sources;
10001 p_info->patch->num_sinks = num_sinks;
10002
10003 for (int i = 0; i < num_sources; i++)
10004 p_info->patch->sources[i] = sources[i];
10005 for (int i = 0; i < num_sinks; i++)
10006 p_info->patch->sinks[i] = sinks[i];
10007
10008 p_info->patch_type = patch_type;
10009 return 0;
10010}
10011
10012audio_patch_handle_t generate_patch_handle()
10013{
10014 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10015 if (++patch_handle < 0)
10016 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10017 return patch_handle;
10018}
10019
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010020int adev_create_audio_patch(struct audio_hw_device *dev,
10021 unsigned int num_sources,
10022 const struct audio_port_config *sources,
10023 unsigned int num_sinks,
10024 const struct audio_port_config *sinks,
10025 audio_patch_handle_t *handle)
10026{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010027 int ret = 0;
10028 struct audio_device *adev = (struct audio_device *)dev;
10029 struct audio_patch_info *p_info = NULL;
10030 patch_type_t patch_type = PATCH_NONE;
10031 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10032 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10033 struct audio_stream_info *s_info = NULL;
10034 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010035 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010036 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10037 bool new_patch = false;
10038 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010039
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010040 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10041 num_sources, num_sinks, *handle);
10042
10043 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10044 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10045 ALOGE("%s: Invalid patch arguments", __func__);
10046 ret = -EINVAL;
10047 goto done;
10048 }
10049
10050 if (num_sources > 1) {
10051 ALOGE("%s: Multiple sources are not supported", __func__);
10052 ret = -EINVAL;
10053 goto done;
10054 }
10055
10056 if (sources == NULL || sinks == NULL) {
10057 ALOGE("%s: Invalid sources or sinks port config", __func__);
10058 ret = -EINVAL;
10059 goto done;
10060 }
10061
10062 ALOGV("%s: source role %d, source type %d", __func__,
10063 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010064 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010065
10066 // Populate source/sink information and fetch stream info
10067 switch (sources[0].type) {
10068 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10069 device_type = sources[0].ext.device.type;
10070 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010071 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10073 patch_type = PATCH_CAPTURE;
10074 io_handle = sinks[0].ext.mix.handle;
10075 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010076 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010077 __func__, device_type, io_handle);
10078 } else {
10079 // Device to device patch is not implemented.
10080 // This space will need changes if audio HAL
10081 // handles device to device patches in the future.
10082 patch_type = PATCH_DEVICE_LOOPBACK;
10083 }
10084 break;
10085 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10086 io_handle = sources[0].ext.mix.handle;
10087 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010088 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010089 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010090 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010091 }
10092 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010093 ALOGD("%s: Playback patch from mix handle %d to device %x",
10094 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095 break;
10096 case AUDIO_PORT_TYPE_SESSION:
10097 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010098 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10099 ret = -EINVAL;
10100 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010101 }
10102
10103 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 // Generate patch info and update patch
10106 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010107 *handle = generate_patch_handle();
10108 p_info = (struct audio_patch_info *)
10109 calloc(1, sizeof(struct audio_patch_info));
10110 if (p_info == NULL) {
10111 ALOGE("%s: Failed to allocate memory", __func__);
10112 pthread_mutex_unlock(&adev->lock);
10113 ret = -ENOMEM;
10114 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010115 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010116 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010117 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010118 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010119 if (p_info == NULL) {
10120 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10121 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010122 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010123 ret = -EINVAL;
10124 goto done;
10125 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010126 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010127 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010128 *handle, p_info, patch_type, new_patch);
10129
10130 // Fetch stream info of associated mix for playback or capture patches
10131 if (p_info->patch_type == PATCH_PLAYBACK ||
10132 p_info->patch_type == PATCH_CAPTURE) {
10133 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10134 if (s_info == NULL) {
10135 ALOGE("%s: Failed to obtain stream info", __func__);
10136 if (new_patch)
10137 free(p_info);
10138 pthread_mutex_unlock(&adev->lock);
10139 ret = -EINVAL;
10140 goto done;
10141 }
10142 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10143 s_info->patch_handle = *handle;
10144 stream = s_info->stream;
10145 }
10146 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147
10148 // Update routing for stream
10149 if (stream != NULL) {
10150 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010151 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010153 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010154 if (ret < 0) {
10155 pthread_mutex_lock(&adev->lock);
10156 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10157 if (new_patch)
10158 free(p_info);
10159 pthread_mutex_unlock(&adev->lock);
10160 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10161 goto done;
10162 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010163 }
10164
10165 // Add new patch to patch map
10166 if (!ret && new_patch) {
10167 pthread_mutex_lock(&adev->lock);
10168 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010170 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010171 }
10172
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010173done:
10174 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010175 num_sources,
10176 sources,
10177 num_sinks,
10178 sinks,
10179 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010180 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010181 num_sources,
10182 sources,
10183 num_sinks,
10184 sinks,
10185 handle);
10186 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010187}
10188
10189int adev_release_audio_patch(struct audio_hw_device *dev,
10190 audio_patch_handle_t handle)
10191{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010192 struct audio_device *adev = (struct audio_device *) dev;
10193 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010194 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010195 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010196
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010197 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10198 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10199 ret = -EINVAL;
10200 goto done;
10201 }
10202
10203 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010204 pthread_mutex_lock(&adev->lock);
10205 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010206 if (p_info == NULL) {
10207 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010208 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010209 ret = -EINVAL;
10210 goto done;
10211 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212 struct audio_patch *patch = p_info->patch;
10213 if (patch == NULL) {
10214 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010215 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010216 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010217 goto done;
10218 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10220 switch (patch->sources[0].type) {
10221 case AUDIO_PORT_TYPE_MIX:
10222 io_handle = patch->sources[0].ext.mix.handle;
10223 break;
10224 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010225 if (p_info->patch_type == PATCH_CAPTURE)
10226 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010227 break;
10228 case AUDIO_PORT_TYPE_SESSION:
10229 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010230 pthread_mutex_unlock(&adev->lock);
10231 ret = -EINVAL;
10232 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010233 }
10234
10235 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010236 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010237 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010238 if (patch_type == PATCH_PLAYBACK ||
10239 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010240 struct audio_stream_info *s_info =
10241 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10242 if (s_info == NULL) {
10243 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10244 pthread_mutex_unlock(&adev->lock);
10245 goto done;
10246 }
10247 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10248 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010249 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010250 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010251
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010252 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010253 struct listnode devices;
10254 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010255 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010256 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010257 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010258 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010259 }
10260
10261 if (ret < 0)
10262 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10263
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010264done:
10265 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10266 audio_extn_auto_hal_release_audio_patch(dev, handle);
10267
10268 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010269 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010270}
10271
10272int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10273{
Derek Chenf13dd492018-11-13 14:53:51 -080010274 int ret = 0;
10275
10276 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10277 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10278 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010279}
10280
10281int adev_set_audio_port_config(struct audio_hw_device *dev,
10282 const struct audio_port_config *config)
10283{
Derek Chenf13dd492018-11-13 14:53:51 -080010284 int ret = 0;
10285
10286 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10287 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10288 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010289}
10290
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010291static int adev_dump(const audio_hw_device_t *device __unused,
10292 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010293{
10294 return 0;
10295}
10296
10297static int adev_close(hw_device_t *device)
10298{
Aalique Grahame22e49102018-12-18 14:23:57 -080010299 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010300 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010301
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010302 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010303 return 0;
10304
10305 pthread_mutex_lock(&adev_init_lock);
10306
10307 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010308 if (audio_extn_spkr_prot_is_enabled())
10309 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010310 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010311 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010312 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010313 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010314 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010315 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010316 audio_extn_utils_release_streams_cfg_lists(
10317 &adev->streams_output_cfg_list,
10318 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010319 if (audio_extn_qap_is_enabled())
10320 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010321 if (audio_extn_qaf_is_enabled())
10322 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010323 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010324 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010325 free(adev->snd_dev_ref_cnt);
10326 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010327 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10328 pcm_params_free(adev->use_case_table[i]);
10329 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010330 if (adev->adm_deinit)
10331 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010332 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010333 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010334 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010335 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010336 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010337 if (adev->device_cfg_params) {
10338 free(adev->device_cfg_params);
10339 adev->device_cfg_params = NULL;
10340 }
Derek Chend2530072014-11-24 12:39:14 -080010341 if(adev->ext_hw_plugin)
10342 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010343 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010344 free_map(adev->patch_map);
10345 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010346 free(device);
10347 adev = NULL;
10348 }
10349 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010350 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010351 return 0;
10352}
10353
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010354/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10355 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10356 * just that it _might_ work.
10357 */
10358static int period_size_is_plausible_for_low_latency(int period_size)
10359{
10360 switch (period_size) {
10361 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010362 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010363 case 240:
10364 case 320:
10365 case 480:
10366 return 1;
10367 default:
10368 return 0;
10369 }
10370}
10371
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010372static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10373{
10374 bool is_snd_card_status = false;
10375 bool is_ext_device_status = false;
10376 char value[32];
10377 int card = -1;
10378 card_status_t status;
10379
10380 if (cookie != adev || !parms)
10381 return;
10382
10383 if (!parse_snd_card_status(parms, &card, &status)) {
10384 is_snd_card_status = true;
10385 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10386 is_ext_device_status = true;
10387 } else {
10388 // not a valid event
10389 return;
10390 }
10391
10392 pthread_mutex_lock(&adev->lock);
10393 if (card == adev->snd_card || is_ext_device_status) {
10394 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010395 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010396 adev->card_status = status;
10397 platform_snd_card_update(adev->platform, status);
10398 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010399 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010400 if (status == CARD_STATUS_OFFLINE)
10401 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010402 } else if (is_ext_device_status) {
10403 platform_set_parameters(adev->platform, parms);
10404 }
10405 }
10406 pthread_mutex_unlock(&adev->lock);
10407 return;
10408}
10409
Weiyin Jiang280ea742020-09-08 20:28:22 +080010410/* adev lock held */
10411int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010412{
10413 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010414 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010415 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010416 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010417
10418 uc_info = get_usecase_from_list(adev, out->usecase);
10419 if (uc_info == NULL) {
10420 ALOGE("%s: Could not find the usecase (%d) in the list",
10421 __func__, out->usecase);
10422 return -EINVAL;
10423 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010424 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010425
Zhou Songbaddf9f2020-11-20 13:57:39 +080010426 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10427 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010428
10429 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010430 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010431 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010432 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010433 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010434 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10435 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010436
10437 if (is_offload_usecase(out->usecase)) {
10438 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010439 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010440 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10441 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10442 } else {
10443 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010444 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010445 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010446 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010447 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010448 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010449 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010450 // mute stream and switch to speaker if suspended
10451 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010452 assign_devices(&devices, &out->device_list);
10453 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010454 list_for_each(node, &adev->usecase_list) {
10455 usecase = node_to_item(node, struct audio_usecase, list);
10456 if ((usecase != uc_info) &&
10457 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10458 usecase->out_snd_device)) {
10459 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10460 break;
10461 }
10462 }
Zhou Song8edbbdb2021-01-14 16:48:03 +080010463 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP) {
10464 out->a2dp_muted = true;
10465 if (is_offload_usecase(out->usecase)) {
10466 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10467 compress_pause(out->compr);
10468 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010469 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010470 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10471 out_set_voip_volume(&out->stream, (float)0, (float)0);
10472 else
10473 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10474
Zhou Song8edbbdb2021-01-14 16:48:03 +080010475 /* wait for stale pcm drained before switching to speaker */
10476 uint32_t latency =
10477 (out->config.period_count * out->config.period_size * 1000) /
10478 (out->config.rate);
10479 usleep(latency * 1000);
10480 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010481 }
10482 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010483 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10484 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010485 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010486 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10487 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010488 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010489 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010490 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010491 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010492 }
10493 ALOGV("%s: exit", __func__);
10494 return 0;
10495}
10496
Haynes Mathew George01156f92018-04-13 15:29:54 -070010497void adev_on_battery_status_changed(bool charging)
10498{
10499 pthread_mutex_lock(&adev->lock);
10500 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10501 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010502 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010503 pthread_mutex_unlock(&adev->lock);
10504}
10505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010506static int adev_open(const hw_module_t *module, const char *name,
10507 hw_device_t **device)
10508{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010509 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010510 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010511 char mixer_ctl_name[128] = {0};
10512 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010513
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010514 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010515 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10516
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010517 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010518 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010519 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010520 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010521 ALOGD("%s: returning existing instance of adev", __func__);
10522 ALOGD("%s: exit", __func__);
10523 pthread_mutex_unlock(&adev_init_lock);
10524 return 0;
10525 }
10526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010527 adev = calloc(1, sizeof(struct audio_device));
10528
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010529 if (!adev) {
10530 pthread_mutex_unlock(&adev_init_lock);
10531 return -ENOMEM;
10532 }
10533
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010534 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10535
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010536 // register audio ext hidl at the earliest
10537 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010538#ifdef DYNAMIC_LOG_ENABLED
10539 register_for_dynamic_logging("hal");
10540#endif
10541
Derek Chenf939fb72018-11-13 13:34:41 -080010542 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010543 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010544 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10545 maj_version = atoi(value);
10546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010547 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010548 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010549 adev->device.common.module = (struct hw_module_t *)module;
10550 adev->device.common.close = adev_close;
10551
10552 adev->device.init_check = adev_init_check;
10553 adev->device.set_voice_volume = adev_set_voice_volume;
10554 adev->device.set_master_volume = adev_set_master_volume;
10555 adev->device.get_master_volume = adev_get_master_volume;
10556 adev->device.set_master_mute = adev_set_master_mute;
10557 adev->device.get_master_mute = adev_get_master_mute;
10558 adev->device.set_mode = adev_set_mode;
10559 adev->device.set_mic_mute = adev_set_mic_mute;
10560 adev->device.get_mic_mute = adev_get_mic_mute;
10561 adev->device.set_parameters = adev_set_parameters;
10562 adev->device.get_parameters = adev_get_parameters;
10563 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10564 adev->device.open_output_stream = adev_open_output_stream;
10565 adev->device.close_output_stream = adev_close_output_stream;
10566 adev->device.open_input_stream = adev_open_input_stream;
10567 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010568 adev->device.create_audio_patch = adev_create_audio_patch;
10569 adev->device.release_audio_patch = adev_release_audio_patch;
10570 adev->device.get_audio_port = adev_get_audio_port;
10571 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010572 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010573 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010574
10575 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010576 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010577 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010578 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010579 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010580 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010581 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010582 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010583 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010584 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010585 /* Init audio and voice feature */
10586 audio_extn_feature_init();
10587 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010588 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010589 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010590 list_init(&adev->active_inputs_list);
10591 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010592 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010593 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10594 audio_extn_utils_hash_eq);
10595 if (!adev->io_streams_map) {
10596 ALOGE("%s: Could not create io streams map", __func__);
10597 ret = -ENOMEM;
10598 goto adev_open_err;
10599 }
10600 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10601 audio_extn_utils_hash_eq);
10602 if (!adev->patch_map) {
10603 ALOGE("%s: Could not create audio patch map", __func__);
10604 ret = -ENOMEM;
10605 goto adev_open_err;
10606 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010607 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010608 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010609 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010610 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010611 adev->perf_lock_opts[0] = 0x101;
10612 adev->perf_lock_opts[1] = 0x20E;
10613 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010614 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010615 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010616 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010617 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010618 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010619
Zhou Song68ebc352019-12-05 17:11:15 +080010620 audio_extn_perf_lock_init();
10621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010622 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010623 adev->platform = platform_init(adev);
10624 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010625 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010626 ret = -EINVAL;
10627 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010628 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010629
Aalique Grahame22e49102018-12-18 14:23:57 -080010630 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010631 if (audio_extn_qap_is_enabled()) {
10632 ret = audio_extn_qap_init(adev);
10633 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010634 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010635 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010636 }
10637 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10638 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10639 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010640
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010641 if (audio_extn_qaf_is_enabled()) {
10642 ret = audio_extn_qaf_init(adev);
10643 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010644 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010645 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010646 }
10647
10648 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10649 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10650 }
10651
Derek Chenae7b0342019-02-08 15:17:04 -080010652 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010653 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10654
Eric Laurentc4aef752013-09-12 17:45:53 -070010655 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10656 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10657 if (adev->visualizer_lib == NULL) {
10658 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10659 } else {
10660 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10661 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010662 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010663 "visualizer_hal_start_output");
10664 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010665 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010666 "visualizer_hal_stop_output");
10667 }
10668 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010669 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010670 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010671 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010672 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010673 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010674 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010675
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010676 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10677 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10678 if (adev->offload_effects_lib == NULL) {
10679 ALOGE("%s: DLOPEN failed for %s", __func__,
10680 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10681 } else {
10682 ALOGV("%s: DLOPEN successful for %s", __func__,
10683 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10684 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010685 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010686 "offload_effects_bundle_hal_start_output");
10687 adev->offload_effects_stop_output =
10688 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10689 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010690 adev->offload_effects_set_hpx_state =
10691 (int (*)(bool))dlsym(adev->offload_effects_lib,
10692 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010693 adev->offload_effects_get_parameters =
10694 (void (*)(struct str_parms *, struct str_parms *))
10695 dlsym(adev->offload_effects_lib,
10696 "offload_effects_bundle_get_parameters");
10697 adev->offload_effects_set_parameters =
10698 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10699 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010700 }
10701 }
10702
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010703 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10704 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10705 if (adev->adm_lib == NULL) {
10706 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10707 } else {
10708 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10709 adev->adm_init = (adm_init_t)
10710 dlsym(adev->adm_lib, "adm_init");
10711 adev->adm_deinit = (adm_deinit_t)
10712 dlsym(adev->adm_lib, "adm_deinit");
10713 adev->adm_register_input_stream = (adm_register_input_stream_t)
10714 dlsym(adev->adm_lib, "adm_register_input_stream");
10715 adev->adm_register_output_stream = (adm_register_output_stream_t)
10716 dlsym(adev->adm_lib, "adm_register_output_stream");
10717 adev->adm_deregister_stream = (adm_deregister_stream_t)
10718 dlsym(adev->adm_lib, "adm_deregister_stream");
10719 adev->adm_request_focus = (adm_request_focus_t)
10720 dlsym(adev->adm_lib, "adm_request_focus");
10721 adev->adm_abandon_focus = (adm_abandon_focus_t)
10722 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010723 adev->adm_set_config = (adm_set_config_t)
10724 dlsym(adev->adm_lib, "adm_set_config");
10725 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10726 dlsym(adev->adm_lib, "adm_request_focus_v2");
10727 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10728 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10729 adev->adm_on_routing_change = (adm_on_routing_change_t)
10730 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010731 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10732 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010733 }
10734 }
10735
Aalique Grahame22e49102018-12-18 14:23:57 -080010736 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010737 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010738 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010739 //initialize this to false for now,
10740 //this will be set to true through set param
10741 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010742
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010743 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010744 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010745
10746 if (k_enable_extended_precision)
10747 adev_verify_devices(adev);
10748
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010749 adev->dsp_bit_width_enforce_mode =
10750 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010751
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010752 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10753 &adev->streams_output_cfg_list,
10754 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010755
Kiran Kandi910e1862013-10-29 13:29:42 -070010756 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010757
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010758 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010759 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010760 trial = atoi(value);
10761 if (period_size_is_plausible_for_low_latency(trial)) {
10762 pcm_config_low_latency.period_size = trial;
10763 pcm_config_low_latency.start_threshold = trial / 4;
10764 pcm_config_low_latency.avail_min = trial / 4;
10765 configured_low_latency_capture_period_size = trial;
10766 }
10767 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010768 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10769 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010770 trial = atoi(value);
10771 if (period_size_is_plausible_for_low_latency(trial)) {
10772 configured_low_latency_capture_period_size = trial;
10773 }
10774 }
10775
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010776 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10777
Eric Laurent4b084132018-10-19 17:33:43 -070010778 adev->camera_orientation = CAMERA_DEFAULT;
10779
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010780 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010781 af_period_multiplier = atoi(value);
10782 if (af_period_multiplier < 0)
10783 af_period_multiplier = 2;
10784 else if (af_period_multiplier > 4)
10785 af_period_multiplier = 4;
10786
10787 ALOGV("new period_multiplier = %d", af_period_multiplier);
10788 }
10789
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010790 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010791
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010792 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010793 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010794 pthread_mutex_unlock(&adev_init_lock);
10795
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010796 if (adev->adm_init)
10797 adev->adm_data = adev->adm_init();
10798
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010799 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010800 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010801
10802 audio_extn_snd_mon_init();
10803 pthread_mutex_lock(&adev->lock);
10804 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10805 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010806 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10807 /*
10808 * if the battery state callback happens before charging can be queried,
10809 * it will be guarded with the adev->lock held in the cb function and so
10810 * the callback value will reflect the latest state
10811 */
10812 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010813 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010814 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010815 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010816 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010817 /* Allocate memory for Device config params */
10818 adev->device_cfg_params = (struct audio_device_config_param*)
10819 calloc(platform_get_max_codec_backend(),
10820 sizeof(struct audio_device_config_param));
10821 if (adev->device_cfg_params == NULL)
10822 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010823
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010824 /*
10825 * Check if new PSPD matrix mixer control is supported. If not
10826 * supported, then set flag so that old mixer ctrl is sent while
10827 * sending pspd coefficients on older kernel version. Query mixer
10828 * control for default pcm id and channel value one.
10829 */
10830 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10831 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10832
10833 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10834 if (!ctl) {
10835 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10836 __func__, mixer_ctl_name);
10837 adev->use_old_pspd_mix_ctrl = true;
10838 }
10839
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010840 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010841 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010842
10843adev_open_err:
10844 free_map(adev->patch_map);
10845 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010846 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010847 pthread_mutex_destroy(&adev->lock);
10848 free(adev);
10849 adev = NULL;
10850 *device = NULL;
10851 pthread_mutex_unlock(&adev_init_lock);
10852 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010853}
10854
10855static struct hw_module_methods_t hal_module_methods = {
10856 .open = adev_open,
10857};
10858
10859struct audio_module HAL_MODULE_INFO_SYM = {
10860 .common = {
10861 .tag = HARDWARE_MODULE_TAG,
10862 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10863 .hal_api_version = HARDWARE_HAL_API_VERSION,
10864 .id = AUDIO_HARDWARE_MODULE_ID,
10865 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010866 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010867 .methods = &hal_module_methods,
10868 },
10869};