blob: 5556c344d92ad95e5e6e0c06731659cd8dc8f302 [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);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003431 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 if (out->compr != NULL) {
3433 compress_stop(out->compr);
3434 while (out->offload_thread_blocked) {
3435 pthread_cond_wait(&out->cond, &out->lock);
3436 }
3437 }
3438}
3439
Varun Balaraje49253e2017-07-06 19:48:56 +05303440bool is_interactive_usecase(audio_usecase_t uc_id)
3441{
3442 unsigned int i;
3443 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3444 if (uc_id == interactive_usecases[i])
3445 return true;
3446 }
3447 return false;
3448}
3449
3450static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3451{
3452 audio_usecase_t ret_uc = USECASE_INVALID;
3453 unsigned int intract_uc_index;
3454 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3455
3456 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3457 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3458 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3459 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3460 ret_uc = interactive_usecases[intract_uc_index];
3461 break;
3462 }
3463 }
3464
3465 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3466 return ret_uc;
3467}
3468
3469static void free_interactive_usecase(struct audio_device *adev,
3470 audio_usecase_t uc_id)
3471{
3472 unsigned int interact_uc_index;
3473 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3474
3475 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3476 if (interactive_usecases[interact_uc_index] == uc_id) {
3477 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3478 break;
3479 }
3480 }
3481 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3482}
3483
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003484bool is_offload_usecase(audio_usecase_t uc_id)
3485{
3486 unsigned int i;
3487 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3488 if (uc_id == offload_usecases[i])
3489 return true;
3490 }
3491 return false;
3492}
3493
Dhananjay Kumarac341582017-02-23 23:42:25 +05303494static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003495{
vivek mehta446c3962015-09-14 10:57:35 -07003496 audio_usecase_t ret_uc = USECASE_INVALID;
3497 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003498 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003499 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303500 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003501 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3502 else
3503 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003504
vivek mehta446c3962015-09-14 10:57:35 -07003505 pthread_mutex_lock(&adev->lock);
3506 if (get_usecase_from_list(adev, ret_uc) != NULL)
3507 ret_uc = USECASE_INVALID;
3508 pthread_mutex_unlock(&adev->lock);
3509
3510 return ret_uc;
3511 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003512
3513 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003514 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3515 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3516 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3517 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003518 break;
3519 }
3520 }
vivek mehta446c3962015-09-14 10:57:35 -07003521
3522 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3523 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003524}
3525
3526static void free_offload_usecase(struct audio_device *adev,
3527 audio_usecase_t uc_id)
3528{
vivek mehta446c3962015-09-14 10:57:35 -07003529 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003530 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003531
3532 if (!adev->multi_offload_enable)
3533 return;
3534
3535 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3536 if (offload_usecases[offload_uc_index] == uc_id) {
3537 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003538 break;
3539 }
3540 }
3541 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3542}
3543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003544static void *offload_thread_loop(void *context)
3545{
3546 struct stream_out *out = (struct stream_out *) context;
3547 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003548 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003551 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003552 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3553
3554 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003555 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003556 out->offload_state = OFFLOAD_STATE_IDLE;
3557 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 for (;;) {
3559 struct offload_cmd *cmd = NULL;
3560 stream_callback_event_t event;
3561 bool send_callback = false;
3562
3563 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3564 __func__, list_empty(&out->offload_cmd_list),
3565 out->offload_state);
3566 if (list_empty(&out->offload_cmd_list)) {
3567 ALOGV("%s SLEEPING", __func__);
3568 pthread_cond_wait(&out->offload_cond, &out->lock);
3569 ALOGV("%s RUNNING", __func__);
3570 continue;
3571 }
3572
3573 item = list_head(&out->offload_cmd_list);
3574 cmd = node_to_item(item, struct offload_cmd, node);
3575 list_remove(item);
3576
3577 ALOGVV("%s STATE %d CMD %d out->compr %p",
3578 __func__, out->offload_state, cmd->cmd, out->compr);
3579
3580 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3581 free(cmd);
3582 break;
3583 }
3584
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003585 // allow OFFLOAD_CMD_ERROR reporting during standby
3586 // this is needed to handle failures during compress_open
3587 // Note however that on a pause timeout, the stream is closed
3588 // and no offload usecase will be active. Therefore this
3589 // special case is needed for compress_open failures alone
3590 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3591 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003592 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003593 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003594 pthread_cond_signal(&out->cond);
3595 continue;
3596 }
3597 out->offload_thread_blocked = true;
3598 pthread_mutex_unlock(&out->lock);
3599 send_callback = false;
3600 switch(cmd->cmd) {
3601 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003602 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003604 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003605 send_callback = true;
3606 event = STREAM_CBK_EVENT_WRITE_READY;
3607 break;
3608 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003609 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303610 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003611 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303612 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003613 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303614 if (ret < 0)
3615 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303616 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303617 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003618 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003619 else
3620 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003621 if (-ENETRESET != ret && !(-EINTR == ret &&
3622 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303623 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303624 pthread_mutex_lock(&out->lock);
3625 out->send_new_metadata = 1;
3626 out->send_next_track_params = true;
3627 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303628 event = STREAM_CBK_EVENT_DRAIN_READY;
3629 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3630 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303631 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003632 break;
3633 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003634 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003635 ret = compress_drain(out->compr);
3636 ALOGD("copl(%p):out of compress_drain", out);
3637 // EINTR check avoids drain interruption due to SSR
3638 if (-ENETRESET != ret && !(-EINTR == ret &&
3639 CARD_STATUS_OFFLINE == out->card_status)) {
3640 send_callback = true;
3641 event = STREAM_CBK_EVENT_DRAIN_READY;
3642 } else
3643 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003644 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303645 case OFFLOAD_CMD_ERROR:
3646 ALOGD("copl(%p): sending error callback to AF", out);
3647 send_callback = true;
3648 event = STREAM_CBK_EVENT_ERROR;
3649 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003650 default:
3651 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3652 break;
3653 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003654 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003655 out->offload_thread_blocked = false;
3656 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003657 if (send_callback && out->client_callback) {
3658 ALOGVV("%s: sending client_callback event %d", __func__, event);
3659 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003660 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003661 free(cmd);
3662 }
3663
3664 pthread_cond_signal(&out->cond);
3665 while (!list_empty(&out->offload_cmd_list)) {
3666 item = list_head(&out->offload_cmd_list);
3667 list_remove(item);
3668 free(node_to_item(item, struct offload_cmd, node));
3669 }
3670 pthread_mutex_unlock(&out->lock);
3671
3672 return NULL;
3673}
3674
3675static int create_offload_callback_thread(struct stream_out *out)
3676{
3677 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3678 list_init(&out->offload_cmd_list);
3679 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3680 offload_thread_loop, out);
3681 return 0;
3682}
3683
3684static int destroy_offload_callback_thread(struct stream_out *out)
3685{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003686 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687 stop_compressed_output_l(out);
3688 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3689
3690 pthread_mutex_unlock(&out->lock);
3691 pthread_join(out->offload_thread, (void **) NULL);
3692 pthread_cond_destroy(&out->offload_cond);
3693
3694 return 0;
3695}
3696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697static int stop_output_stream(struct stream_out *out)
3698{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303699 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 struct audio_usecase *uc_info;
3701 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003702 bool has_voip_usecase =
3703 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704
Eric Laurent994a6932013-07-17 11:51:42 -07003705 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003706 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 uc_info = get_usecase_from_list(adev, out->usecase);
3708 if (uc_info == NULL) {
3709 ALOGE("%s: Could not find the usecase (%d) in the list",
3710 __func__, out->usecase);
3711 return -EINVAL;
3712 }
3713
Zhou Songbaddf9f2020-11-20 13:57:39 +08003714 out->a2dp_muted = false;
3715
Derek Chenea197282019-01-07 17:35:01 -08003716 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3717 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003718
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003719 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303720 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003721 if (adev->visualizer_stop_output != NULL)
3722 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003723
3724 audio_extn_dts_remove_state_notifier_node(out->usecase);
3725
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003726 if (adev->offload_effects_stop_output != NULL)
3727 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003728 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3729 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3730 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003731 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003732
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003733 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3734 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003735 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003736 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003737
Eric Laurent150dbfe2013-02-27 14:31:02 -08003738 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003739 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003740
3741 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003742 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003743 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3744 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745
Aalique Grahame22e49102018-12-18 14:23:57 -08003746 audio_extn_extspk_update(adev->extspk);
3747
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003748 if (is_offload_usecase(out->usecase)) {
3749 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3750 adev->dsp_bit_width_enforce_mode,
3751 false);
3752 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003753 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003754 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3755 false);
3756
3757 if (ret != 0)
3758 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3759 /* default service interval was successfully updated,
3760 reopen USB backend with new service interval */
3761 ret = 0;
3762 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003763
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003764 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303765 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003766 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303767 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003768 ALOGV("Disable passthrough , reset mixer to pcm");
3769 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003770#ifdef AUDIO_GKI_ENABLED
3771 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3772 out->compr_config.codec->reserved[0] = 0;
3773#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003774 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003775#endif
Mingming Yin21854652016-04-13 11:54:02 -07003776 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003777 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3778 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003779
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303780 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003781 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303782 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303783
Manish Dewangan21a850a2017-08-14 12:03:55 +05303784 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003785 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3786 if (ret < 0)
3787 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3788 }
3789
Zhou Song642ec432020-12-23 16:11:10 +08003790 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003791 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003792 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003793 struct listnode *node;
3794 struct audio_usecase *usecase;
3795 list_for_each(node, &adev->usecase_list) {
3796 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003797 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3798 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303799 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003800 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003801 continue;
3802
3803 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3804 __func__, usecase->id, use_case_table[usecase->id],
3805 out->usecase, use_case_table[out->usecase]);
3806 select_devices(adev, usecase->id);
3807 }
3808 }
3809
Garmond Leung5fd0b552018-04-17 11:56:12 -07003810 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003811 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 return ret;
3813}
3814
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003815struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3816 unsigned int flags, unsigned int pcm_open_retry_count,
3817 struct pcm_config *config)
3818{
3819 struct pcm* pcm = NULL;
3820
3821 while (1) {
3822 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3823 if (pcm == NULL || !pcm_is_ready(pcm)) {
3824 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3825 if (pcm != NULL) {
3826 pcm_close(pcm);
3827 pcm = NULL;
3828 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003829 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003830 return NULL;
3831
Weiyin Jiang72197252019-10-09 11:49:32 +08003832 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003833 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3834 continue;
3835 }
3836 break;
3837 }
3838
3839 if (pcm_is_ready(pcm)) {
3840 int ret = pcm_prepare(pcm);
3841 if (ret < 0) {
3842 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3843 pcm_close(pcm);
3844 pcm = NULL;
3845 }
3846 }
3847
3848 return pcm;
3849}
3850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851int start_output_stream(struct stream_out *out)
3852{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 struct audio_usecase *uc_info;
3855 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003856 char mixer_ctl_name[128];
3857 struct mixer_ctl *ctl = NULL;
3858 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303859 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003860 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861
Haynes Mathew George380745d2017-10-04 15:27:45 -07003862 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003863 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3864 ret = -EINVAL;
3865 goto error_config;
3866 }
3867
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003868 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303869 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003870 get_device_types(&out->device_list), is_haptic_usecase);
3871
3872 bool is_speaker_active = compare_device_type(&out->device_list,
3873 AUDIO_DEVICE_OUT_SPEAKER);
3874 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3875 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303876
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303877 if (CARD_STATUS_OFFLINE == out->card_status ||
3878 CARD_STATUS_OFFLINE == adev->card_status) {
3879 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303880 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003881 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303882 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303883
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003884 //Update incall music usecase to reflect correct voice session
3885 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3886 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3887 if (ret != 0) {
3888 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3889 __func__, ret);
3890 goto error_config;
3891 }
3892 }
3893
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003894 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003895 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003896 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303897 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303898 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003899 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303900 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3901 ret = -EAGAIN;
3902 goto error_config;
3903 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303904 }
3905 }
3906 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003907 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303908 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003909 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303910 //combo usecase just by pass a2dp
3911 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003912 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303913 } else {
3914 ALOGE("%s: SCO profile is not ready, return error", __func__);
3915 ret = -EAGAIN;
3916 goto error_config;
3917 }
3918 }
3919 }
3920
Eric Laurentb23d5282013-05-14 15:27:20 -07003921 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922 if (out->pcm_device_id < 0) {
3923 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3924 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003925 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003926 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 }
3928
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003929 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003930 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3931 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003932 if (adev->haptic_pcm_device_id < 0) {
3933 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3934 __func__, adev->haptic_pcm_device_id, out->usecase);
3935 ret = -EINVAL;
3936 goto error_config;
3937 }
3938 }
3939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003941
3942 if (!uc_info) {
3943 ret = -ENOMEM;
3944 goto error_config;
3945 }
3946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947 uc_info->id = out->usecase;
3948 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003949 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003950 list_init(&uc_info->device_list);
3951 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003952 uc_info->in_snd_device = SND_DEVICE_NONE;
3953 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003954
3955 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003956 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003957 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3958 /* USB backend is not reopened immediately.
3959 This is eventually done as part of select_devices */
3960 }
3961
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003962 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963
Wei Wangf7ca6c92017-11-21 14:51:20 -08003964 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303965 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3966 adev->perf_lock_opts,
3967 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303968
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003969 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303970 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303971 if (audio_extn_passthru_is_enabled() &&
3972 audio_extn_passthru_is_passthrough_stream(out)) {
3973 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303974 }
3975 }
3976
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003977 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003978 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303979 if (!a2dp_combo) {
3980 check_a2dp_restore_l(adev, out, false);
3981 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003982 struct listnode dev;
3983 list_init(&dev);
3984 assign_devices(&dev, &out->device_list);
3985 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3986 reassign_device_list(&out->device_list,
3987 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003988 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003989 reassign_device_list(&out->device_list,
3990 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303991 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003992 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303993 }
3994 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303995 select_devices(adev, out->usecase);
3996 if (is_a2dp_out_device_type(&out->device_list) &&
3997 !adev->a2dp_started) {
3998 if (is_speaker_active || is_speaker_safe_active) {
3999 struct listnode dev;
4000 list_init(&dev);
4001 assign_devices(&dev, &out->device_list);
4002 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4003 reassign_device_list(&out->device_list,
4004 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4005 else
4006 reassign_device_list(&out->device_list,
4007 AUDIO_DEVICE_OUT_SPEAKER, "");
4008 select_devices(adev, out->usecase);
4009 assign_devices(&out->device_list, &dev);
4010 } else {
4011 ret = -EINVAL;
4012 goto error_open;
4013 }
4014 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304015 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004016
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004017 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4018 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004019 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004020 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004021
Derek Chenea197282019-01-07 17:35:01 -08004022 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4023 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004024
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004025 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4026 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004027
4028 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004029 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004030 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4031 ALOGE("%s: pcm stream not ready", __func__);
4032 goto error_open;
4033 }
4034 ret = pcm_start(out->pcm);
4035 if (ret < 0) {
4036 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4037 goto error_open;
4038 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004039 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004040 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004041 unsigned int flags = PCM_OUT;
4042 unsigned int pcm_open_retry_count = 0;
4043 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4044 flags |= PCM_MMAP | PCM_NOIRQ;
4045 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004046 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004047 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004048 } else
4049 flags |= PCM_MONOTONIC;
4050
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004051 if ((adev->vr_audio_mode_enabled) &&
4052 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4053 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4054 "PCM_Dev %d Topology", out->pcm_device_id);
4055 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4056 if (!ctl) {
4057 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4058 __func__, mixer_ctl_name);
4059 } else {
4060 //if success use ULLPP
4061 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4062 __func__, mixer_ctl_name, out->pcm_device_id);
4063 //There is a still a possibility that some sessions
4064 // that request for FAST|RAW when 3D audio is active
4065 //can go through ULLPP. Ideally we expects apps to
4066 //listen to audio focus and stop concurrent playback
4067 //Also, we will look for mode flag (voice_in_communication)
4068 //before enabling the realtime flag.
4069 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4070 }
4071 }
4072
Surendar Karka91fa3682018-07-02 18:12:12 +05304073 if (out->realtime)
4074 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004075 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304076
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004077 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4078 flags, pcm_open_retry_count,
4079 &(out->config));
4080 if (out->pcm == NULL) {
4081 ret = -EIO;
4082 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004083 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004084
4085 if (is_haptic_usecase) {
4086 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4087 adev->haptic_pcm_device_id,
4088 flags, pcm_open_retry_count,
4089 &(adev->haptics_config));
4090 // failure to open haptics pcm shouldnt stop audio,
4091 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004092
4093 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4094 ALOGD("%s: enable haptic audio synchronization", __func__);
4095 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4096 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004097 }
4098
Surendar Karka91fa3682018-07-02 18:12:12 +05304099 if (!out->realtime)
4100 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004101 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004102
Zhou Song2b8f28f2017-09-11 10:51:38 +08004103 // apply volume for voip playback after path is set up
4104 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4105 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304106 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4107 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304108 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4109 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004110 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4111 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304112 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004113 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004114 /*
4115 * set custom channel map if:
4116 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4117 * 2. custom channel map has been set by client
4118 * else default channel map of FC/FR/FL can always be set to DSP
4119 */
4120 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4121 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004122 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004123 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4124 adev->dsp_bit_width_enforce_mode,
4125 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004127 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004128 out->compr = compress_open(adev->snd_card,
4129 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004130 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004131 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304132 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304133 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4134 adev->card_status = CARD_STATUS_OFFLINE;
4135 out->card_status = CARD_STATUS_OFFLINE;
4136 ret = -EIO;
4137 goto error_open;
4138 }
4139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004140 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004141 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004142 compress_close(out->compr);
4143 out->compr = NULL;
4144 ret = -EIO;
4145 goto error_open;
4146 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304147 /* compress_open sends params of the track, so reset the flag here */
4148 out->is_compr_metadata_avail = false;
4149
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004150 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004152
Fred Oh3f43e742015-03-04 18:42:34 -08004153 /* Since small bufs uses blocking writes, a write will be blocked
4154 for the default max poll time (20s) in the event of an SSR.
4155 Reduce the poll time to observe and deal with SSR faster.
4156 */
Ashish Jain5106d362016-05-11 19:23:33 +05304157 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004158 compress_set_max_poll_wait(out->compr, 1000);
4159 }
4160
Manish Dewangan69426c82017-01-30 17:35:36 +05304161 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304162 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304163
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004164 audio_extn_dts_create_state_notifier_node(out->usecase);
4165 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4166 popcount(out->channel_mask),
4167 out->playback_started);
4168
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004169#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304170 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004171 audio_extn_dolby_send_ddp_endp_params(adev);
4172#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304173 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4174 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004175 if (adev->visualizer_start_output != NULL)
4176 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4177 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304178 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004179 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004180 }
Derek Chenf13dd492018-11-13 14:53:51 -08004181
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004182 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004183 /* Update cached volume from media to offload/direct stream */
4184 struct listnode *node = NULL;
4185 list_for_each(node, &adev->active_outputs_list) {
4186 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4187 streams_output_ctxt_t,
4188 list);
4189 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4190 out->volume_l = out_ctxt->output->volume_l;
4191 out->volume_r = out_ctxt->output->volume_r;
4192 }
4193 }
4194 out_set_compr_volume(&out->stream,
4195 out->volume_l, out->volume_r);
4196 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004198
4199 if (ret == 0) {
4200 register_out_stream(out);
4201 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004202 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4203 ALOGE("%s: pcm stream not ready", __func__);
4204 goto error_open;
4205 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004206 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004207 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004208 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004209 if (ret < 0)
4210 goto error_open;
4211 }
4212 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004213 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304214 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304215 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004216
vivek mehtad15d2bf2019-05-17 13:35:10 -07004217 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4218 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4219 audio_low_latency_hint_start();
4220 }
4221
Manish Dewangan21a850a2017-08-14 12:03:55 +05304222 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004223 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004224 if (ret < 0)
4225 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4226 }
4227
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004228 // consider a scenario where on pause lower layers are tear down.
4229 // so on resume, swap mixer control need to be sent only when
4230 // backend is active, hence rather than sending from enable device
4231 // sending it from start of streamtream
4232
4233 platform_set_swap_channels(adev, true);
4234
Haynes Mathew George380745d2017-10-04 15:27:45 -07004235 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304236 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004237 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004238error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004239 if (adev->haptic_pcm) {
4240 pcm_close(adev->haptic_pcm);
4241 adev->haptic_pcm = NULL;
4242 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004243 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304244 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004246error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304247 /*
4248 * sleep 50ms to allow sufficient time for kernel
4249 * drivers to recover incases like SSR.
4250 */
4251 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004252error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004253 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304254 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004255 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256}
4257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258static int check_input_parameters(uint32_t sample_rate,
4259 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004260 int channel_count,
4261 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004263 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304265 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4266 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4267 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004268 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004269 !audio_extn_compr_cap_format_supported(format) &&
4270 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004271 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004272
Aalique Grahame22e49102018-12-18 14:23:57 -08004273 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4274 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4275 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4276 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4277 return -EINVAL;
4278 }
4279
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004280 switch (channel_count) {
4281 case 1:
4282 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304283 case 3:
4284 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004285 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004286 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304287 case 10:
4288 case 12:
4289 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004290 break;
4291 default:
4292 ret = -EINVAL;
4293 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294
4295 switch (sample_rate) {
4296 case 8000:
4297 case 11025:
4298 case 12000:
4299 case 16000:
4300 case 22050:
4301 case 24000:
4302 case 32000:
4303 case 44100:
4304 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004305 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304306 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004307 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304308 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 break;
4310 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004311 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312 }
4313
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004314 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315}
4316
Naresh Tanniru04f71882018-06-26 17:46:22 +05304317
4318/** Add a value in a list if not already present.
4319 * @return true if value was successfully inserted or already present,
4320 * false if the list is full and does not contain the value.
4321 */
4322static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4323 for (size_t i = 0; i < list_length; i++) {
4324 if (list[i] == value) return true; // value is already present
4325 if (list[i] == 0) { // no values in this slot
4326 list[i] = value;
4327 return true; // value inserted
4328 }
4329 }
4330 return false; // could not insert value
4331}
4332
4333/** Add channel_mask in supported_channel_masks if not already present.
4334 * @return true if channel_mask was successfully inserted or already present,
4335 * false if supported_channel_masks is full and does not contain channel_mask.
4336 */
4337static void register_channel_mask(audio_channel_mask_t channel_mask,
4338 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4339 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4340 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4341}
4342
4343/** Add format in supported_formats if not already present.
4344 * @return true if format was successfully inserted or already present,
4345 * false if supported_formats is full and does not contain format.
4346 */
4347static void register_format(audio_format_t format,
4348 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4349 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4350 "%s: stream can not declare supporting its format %x", __func__, format);
4351}
4352/** Add sample_rate in supported_sample_rates if not already present.
4353 * @return true if sample_rate was successfully inserted or already present,
4354 * false if supported_sample_rates is full and does not contain sample_rate.
4355 */
4356static void register_sample_rate(uint32_t sample_rate,
4357 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4358 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4359 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4360}
4361
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004362static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4363{
4364 uint32_t high = num1, low = num2, temp = 0;
4365
4366 if (!num1 || !num2)
4367 return 0;
4368
4369 if (num1 < num2) {
4370 high = num2;
4371 low = num1;
4372 }
4373
4374 while (low != 0) {
4375 temp = low;
4376 low = high % low;
4377 high = temp;
4378 }
4379 return (num1 * num2)/high;
4380}
4381
4382static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4383{
4384 uint32_t remainder = 0;
4385
4386 if (!multiplier)
4387 return num;
4388
4389 remainder = num % multiplier;
4390 if (remainder)
4391 num += (multiplier - remainder);
4392
4393 return num;
4394}
4395
Aalique Grahame22e49102018-12-18 14:23:57 -08004396static size_t get_stream_buffer_size(size_t duration_ms,
4397 uint32_t sample_rate,
4398 audio_format_t format,
4399 int channel_count,
4400 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401{
4402 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004403 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004404
Aalique Grahame22e49102018-12-18 14:23:57 -08004405 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004406 if (is_low_latency)
4407 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304408
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004409 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004410 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411
Ralf Herzbd08d632018-09-28 15:50:49 +02004412 /* make sure the size is multiple of 32 bytes and additionally multiple of
4413 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004414 * At 48 kHz mono 16-bit PCM:
4415 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4416 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004417 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004418 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004419 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004420
4421 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422}
4423
Aalique Grahame22e49102018-12-18 14:23:57 -08004424static size_t get_input_buffer_size(uint32_t sample_rate,
4425 audio_format_t format,
4426 int channel_count,
4427 bool is_low_latency)
4428{
4429 /* Don't know if USB HIFI in this context so use true to be conservative */
4430 if (check_input_parameters(sample_rate, format, channel_count,
4431 true /*is_usb_hifi */) != 0)
4432 return 0;
4433
4434 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4435 sample_rate,
4436 format,
4437 channel_count,
4438 is_low_latency);
4439}
4440
Derek Chenf6318be2017-06-12 17:16:24 -04004441size_t get_output_period_size(uint32_t sample_rate,
4442 audio_format_t format,
4443 int channel_count,
4444 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304445{
4446 size_t size = 0;
4447 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4448
4449 if ((duration == 0) || (sample_rate == 0) ||
4450 (bytes_per_sample == 0) || (channel_count == 0)) {
4451 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4452 bytes_per_sample, channel_count);
4453 return -EINVAL;
4454 }
4455
4456 size = (sample_rate *
4457 duration *
4458 bytes_per_sample *
4459 channel_count) / 1000;
4460 /*
4461 * To have same PCM samples for all channels, the buffer size requires to
4462 * be multiple of (number of channels * bytes per sample)
4463 * For writes to succeed, the buffer must be written at address which is multiple of 32
4464 */
4465 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4466
4467 return (size/(channel_count * bytes_per_sample));
4468}
4469
Zhou Song48453a02018-01-10 17:50:59 +08004470static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304471{
4472 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004473 uint64_t written_frames = 0;
4474 uint64_t kernel_frames = 0;
4475 uint64_t dsp_frames = 0;
4476 uint64_t signed_frames = 0;
4477 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304478
4479 /* This adjustment accounts for buffering after app processor.
4480 * It is based on estimated DSP latency per use case, rather than exact.
4481 */
George Gao9ba8a142020-07-23 14:30:03 -07004482 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004483 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304484
Zhou Song48453a02018-01-10 17:50:59 +08004485 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004486 written_frames = out->written /
4487 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4488
Ashish Jain5106d362016-05-11 19:23:33 +05304489 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4490 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4491 * hence only estimate.
4492 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004493 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4494 kernel_frames = kernel_buffer_size /
4495 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304496
Weiyin Jiang4813da12020-05-28 00:37:28 +08004497 if (written_frames >= (kernel_frames + dsp_frames))
4498 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304499
Zhou Song48453a02018-01-10 17:50:59 +08004500 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304501 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004502 if (timestamp != NULL )
4503 *timestamp = out->writeAt;
4504 } else if (timestamp != NULL) {
4505 clock_gettime(CLOCK_MONOTONIC, timestamp);
4506 }
4507 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304508
Weiyin Jiang4813da12020-05-28 00:37:28 +08004509 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4510 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304511
4512 return actual_frames_rendered;
4513}
4514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4516{
4517 struct stream_out *out = (struct stream_out *)stream;
4518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520}
4521
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004522static int out_set_sample_rate(struct audio_stream *stream __unused,
4523 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524{
4525 return -ENOSYS;
4526}
4527
4528static size_t out_get_buffer_size(const struct audio_stream *stream)
4529{
4530 struct stream_out *out = (struct stream_out *)stream;
4531
Varun Balaraje49253e2017-07-06 19:48:56 +05304532 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304533 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304534 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304535 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4536 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4537 else
4538 return out->compr_config.fragment_size;
4539 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004540 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304541 else if (is_offload_usecase(out->usecase) &&
4542 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304543 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004544
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004545 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004546 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547}
4548
4549static uint32_t out_get_channels(const struct audio_stream *stream)
4550{
4551 struct stream_out *out = (struct stream_out *)stream;
4552
4553 return out->channel_mask;
4554}
4555
4556static audio_format_t out_get_format(const struct audio_stream *stream)
4557{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004558 struct stream_out *out = (struct stream_out *)stream;
4559
4560 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561}
4562
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004563static int out_set_format(struct audio_stream *stream __unused,
4564 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565{
4566 return -ENOSYS;
4567}
4568
4569static int out_standby(struct audio_stream *stream)
4570{
4571 struct stream_out *out = (struct stream_out *)stream;
4572 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004573 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004574
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304575 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4576 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004578 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004580 if (adev->adm_deregister_stream)
4581 adev->adm_deregister_stream(adev->adm_data, out->handle);
4582
Weiyin Jiang280ea742020-09-08 20:28:22 +08004583 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004584 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004585 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004586
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004587 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004589 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4590 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304591 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004592 pthread_mutex_unlock(&adev->lock);
4593 pthread_mutex_unlock(&out->lock);
4594 ALOGD("VOIP output entered standby");
4595 return 0;
4596 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004597 if (out->pcm) {
4598 pcm_close(out->pcm);
4599 out->pcm = NULL;
4600 }
Meng Wanga09da002020-04-20 12:56:04 +08004601 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4602 if (adev->haptic_pcm) {
4603 pcm_close(adev->haptic_pcm);
4604 adev->haptic_pcm = NULL;
4605 }
4606
4607 if (adev->haptic_buffer != NULL) {
4608 free(adev->haptic_buffer);
4609 adev->haptic_buffer = NULL;
4610 adev->haptic_buffer_size = 0;
4611 }
4612 adev->haptic_pcm_device_id = 0;
4613 }
4614
Haynes Mathew George16081042017-05-31 17:16:49 -07004615 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4616 do_stop = out->playback_started;
4617 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004618
4619 if (out->mmap_shared_memory_fd >= 0) {
4620 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4621 __func__, out->mmap_shared_memory_fd);
4622 close(out->mmap_shared_memory_fd);
4623 out->mmap_shared_memory_fd = -1;
4624 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004625 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004626 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004627 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304628 out->send_next_track_params = false;
4629 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004630 out->gapless_mdata.encoder_delay = 0;
4631 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004632 if (out->compr != NULL) {
4633 compress_close(out->compr);
4634 out->compr = NULL;
4635 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004636 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004637 if (do_stop) {
4638 stop_output_stream(out);
4639 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304640 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004641 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004642 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643 }
4644 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004645 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 return 0;
4647}
4648
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304649static int out_on_error(struct audio_stream *stream)
4650{
4651 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004652 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304653
4654 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004655 // always send CMD_ERROR for offload streams, this
4656 // is needed e.g. when SSR happens within compress_open
4657 // since the stream is active, offload_callback_thread is also active.
4658 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4659 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004660 }
4661 pthread_mutex_unlock(&out->lock);
4662
4663 status = out_standby(&out->stream.common);
4664
4665 lock_output_stream(out);
4666 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004667 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304668 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304669
4670 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4671 ALOGD("Setting previous card status if offline");
4672 out->prev_card_status_offline = true;
4673 }
4674
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304675 pthread_mutex_unlock(&out->lock);
4676
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004677 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304678}
4679
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304680/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004681 * standby implementation without locks, assumes that the callee already
4682 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304683 */
4684int out_standby_l(struct audio_stream *stream)
4685{
4686 struct stream_out *out = (struct stream_out *)stream;
4687 struct audio_device *adev = out->dev;
4688
4689 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4690 stream, out->usecase, use_case_table[out->usecase]);
4691
4692 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004693 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304694 if (adev->adm_deregister_stream)
4695 adev->adm_deregister_stream(adev->adm_data, out->handle);
4696
Weiyin Jiang280ea742020-09-08 20:28:22 +08004697 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304698 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004699 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304700
4701 out->standby = true;
4702 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4703 voice_extn_compress_voip_close_output_stream(stream);
4704 out->started = 0;
4705 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004706 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304707 return 0;
4708 } else if (!is_offload_usecase(out->usecase)) {
4709 if (out->pcm) {
4710 pcm_close(out->pcm);
4711 out->pcm = NULL;
4712 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004713 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4714 if (adev->haptic_pcm) {
4715 pcm_close(adev->haptic_pcm);
4716 adev->haptic_pcm = NULL;
4717 }
4718
4719 if (adev->haptic_buffer != NULL) {
4720 free(adev->haptic_buffer);
4721 adev->haptic_buffer = NULL;
4722 adev->haptic_buffer_size = 0;
4723 }
4724 adev->haptic_pcm_device_id = 0;
4725 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304726 } else {
4727 ALOGD("copl(%p):standby", out);
4728 out->send_next_track_params = false;
4729 out->is_compr_metadata_avail = false;
4730 out->gapless_mdata.encoder_delay = 0;
4731 out->gapless_mdata.encoder_padding = 0;
4732 if (out->compr != NULL) {
4733 compress_close(out->compr);
4734 out->compr = NULL;
4735 }
4736 }
4737 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004738 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304739 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004740 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304741 return 0;
4742}
4743
Aalique Grahame22e49102018-12-18 14:23:57 -08004744static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004745{
Aalique Grahame22e49102018-12-18 14:23:57 -08004746 struct stream_out *out = (struct stream_out *)stream;
4747
4748 // We try to get the lock for consistency,
4749 // but it isn't necessary for these variables.
4750 // If we're not in standby, we may be blocked on a write.
4751 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4752 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4753 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4754
Andy Hunga1f48fa2019-07-01 18:14:53 -07004755 char buffer[256]; // for statistics formatting
4756 if (!is_offload_usecase(out->usecase)) {
4757 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4758 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4759 }
4760
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004761 if (out->start_latency_ms.n > 0) {
4762 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4763 dprintf(fd, " Start latency ms: %s\n", buffer);
4764 }
4765
Aalique Grahame22e49102018-12-18 14:23:57 -08004766 if (locked) {
4767 pthread_mutex_unlock(&out->lock);
4768 }
4769
4770 // dump error info
4771 (void)error_log_dump(
4772 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 return 0;
4775}
4776
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004777static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4778{
4779 int ret = 0;
4780 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004781
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004782 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004783 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004784 return -EINVAL;
4785 }
4786
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304787 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004788
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004789 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4790 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304791 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004792 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004793 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4794 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304795 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004796 }
4797
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004798 ALOGV("%s new encoder delay %u and padding %u", __func__,
4799 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4800
4801 return 0;
4802}
4803
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004804static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4805{
4806 return out == adev->primary_output || out == adev->voice_tx_output;
4807}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004808
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304809// note: this call is safe only if the stream_cb is
4810// removed first in close_output_stream (as is done now).
4811static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4812{
4813 if (!stream || !parms)
4814 return;
4815
4816 struct stream_out *out = (struct stream_out *)stream;
4817 struct audio_device *adev = out->dev;
4818
4819 card_status_t status;
4820 int card;
4821 if (parse_snd_card_status(parms, &card, &status) < 0)
4822 return;
4823
4824 pthread_mutex_lock(&adev->lock);
4825 bool valid_cb = (card == adev->snd_card);
4826 pthread_mutex_unlock(&adev->lock);
4827
4828 if (!valid_cb)
4829 return;
4830
4831 lock_output_stream(out);
4832 if (out->card_status != status)
4833 out->card_status = status;
4834 pthread_mutex_unlock(&out->lock);
4835
4836 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4837 use_case_table[out->usecase],
4838 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4839
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304840 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304841 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304842 if (voice_is_call_state_active(adev) &&
4843 out == adev->primary_output) {
4844 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4845 pthread_mutex_lock(&adev->lock);
4846 voice_stop_call(adev);
4847 adev->mode = AUDIO_MODE_NORMAL;
4848 pthread_mutex_unlock(&adev->lock);
4849 }
4850 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304851 return;
4852}
4853
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004855 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004856{
4857 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004858 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004859 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004860 bool bypass_a2dp = false;
4861 bool reconfig = false;
4862 unsigned long service_interval = 0;
4863
4864 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004865 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4866
4867 list_init(&new_devices);
4868 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004869
4870 lock_output_stream(out);
4871 pthread_mutex_lock(&adev->lock);
4872
4873 /*
4874 * When HDMI cable is unplugged the music playback is paused and
4875 * the policy manager sends routing=0. But the audioflinger continues
4876 * to write data until standby time (3sec). As the HDMI core is
4877 * turned off, the write gets blocked.
4878 * Avoid this by routing audio to speaker until standby.
4879 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004880 if (is_single_device_type_equal(&out->device_list,
4881 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004882 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004883 !audio_extn_passthru_is_passthrough_stream(out) &&
4884 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004885 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004886 }
4887 /*
4888 * When A2DP is disconnected the
4889 * music playback is paused and the policy manager sends routing=0
4890 * But the audioflinger continues to write data until standby time
4891 * (3sec). As BT is turned off, the write gets blocked.
4892 * Avoid this by routing audio to speaker until standby.
4893 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004894 if (is_a2dp_out_device_type(&out->device_list) &&
4895 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004896 !audio_extn_a2dp_source_is_ready() &&
4897 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004898 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004899 }
4900 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08004901 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004902 * and the policy manager send routing=0. But if the USB is connected
4903 * back before the standby time, AFE is not closed and opened
4904 * when USB is connected back. So routing to speker will guarantee
4905 * AFE reconfiguration and AFE will be opend once USB is connected again
4906 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004907 if (is_usb_out_device_type(&out->device_list) &&
4908 list_empty(&new_devices) &&
4909 !audio_extn_usb_connected(NULL)) {
4910 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4911 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004912 /* To avoid a2dp to sco overlapping / BT device improper state
4913 * check with BT lib about a2dp streaming support before routing
4914 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004915 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004916 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004917 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4918 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004919 //combo usecase just by pass a2dp
4920 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4921 bypass_a2dp = true;
4922 } else {
4923 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4924 /* update device to a2dp and don't route as BT returned error
4925 * However it is still possible a2dp routing called because
4926 * of current active device disconnection (like wired headset)
4927 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004928 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004929 pthread_mutex_unlock(&adev->lock);
4930 pthread_mutex_unlock(&out->lock);
4931 goto error;
4932 }
4933 }
4934 }
4935
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004936 // Workaround: If routing to an non existing usb device, fail gracefully
4937 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004938 if (is_usb_out_device_type(&new_devices)) {
4939 struct str_parms *parms =
4940 str_parms_create_str(get_usb_device_address(&new_devices));
4941 if (!parms)
4942 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08004943 if (!audio_extn_usb_connected(NULL)) {
4944 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004945 pthread_mutex_unlock(&adev->lock);
4946 pthread_mutex_unlock(&out->lock);
4947 str_parms_destroy(parms);
4948 ret = -ENOSYS;
4949 goto error;
4950 }
4951 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004952 }
4953
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004954 // Workaround: If routing to an non existing hdmi device, fail gracefully
4955 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4956 (platform_get_edid_info_v2(adev->platform,
4957 out->extconn.cs.controller,
4958 out->extconn.cs.stream) != 0)) {
4959 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4960 pthread_mutex_unlock(&adev->lock);
4961 pthread_mutex_unlock(&out->lock);
4962 ret = -ENOSYS;
4963 goto error;
4964 }
4965
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004966 /*
4967 * select_devices() call below switches all the usecases on the same
4968 * backend to the new device. Refer to check_usecases_codec_backend() in
4969 * the select_devices(). But how do we undo this?
4970 *
4971 * For example, music playback is active on headset (deep-buffer usecase)
4972 * and if we go to ringtones and select a ringtone, low-latency usecase
4973 * will be started on headset+speaker. As we can't enable headset+speaker
4974 * and headset devices at the same time, select_devices() switches the music
4975 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4976 * So when the ringtone playback is completed, how do we undo the same?
4977 *
4978 * We are relying on the out_set_parameters() call on deep-buffer output,
4979 * once the ringtone playback is ended.
4980 * NOTE: We should not check if the current devices are same as new devices.
4981 * Because select_devices() must be called to switch back the music
4982 * playback to headset.
4983 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004984 if (!list_empty(&new_devices)) {
4985 bool same_dev = compare_devices(&out->device_list, &new_devices);
4986 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004987
4988 if (output_drives_call(adev, out)) {
4989 if (!voice_is_call_state_active(adev)) {
4990 if (adev->mode == AUDIO_MODE_IN_CALL) {
4991 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004992 ret = voice_start_call(adev);
4993 }
4994 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08004995 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004996 adev->current_call_output = out;
4997 voice_update_devices_for_all_voice_usecases(adev);
4998 }
4999 }
5000
Mingshu Pang971ff702020-09-09 15:28:22 +08005001 if (is_usb_out_device_type(&out->device_list)) {
5002 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5003 audio_extn_usb_set_service_interval(true /*playback*/,
5004 service_interval,
5005 &reconfig);
5006 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5007 }
5008
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005009 if (!out->standby) {
5010 if (!same_dev) {
5011 ALOGV("update routing change");
5012 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5013 adev->perf_lock_opts,
5014 adev->perf_lock_opts_size);
5015 if (adev->adm_on_routing_change)
5016 adev->adm_on_routing_change(adev->adm_data,
5017 out->handle);
5018 }
5019 if (!bypass_a2dp) {
5020 select_devices(adev, out->usecase);
5021 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005022 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5023 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005024 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005025 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005026 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005027 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005028 }
5029
5030 if (!same_dev) {
5031 // on device switch force swap, lower functions will make sure
5032 // to check if swap is allowed or not.
5033 platform_set_swap_channels(adev, true);
5034 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5035 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005036 pthread_mutex_lock(&out->latch_lock);
5037 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5038 if (out->a2dp_muted) {
5039 out->a2dp_muted = false;
5040 if (is_offload_usecase(out->usecase))
5041 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5042 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5043 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005044 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005045 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005046 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5047 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5048 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 }
5050 }
5051
5052 pthread_mutex_unlock(&adev->lock);
5053 pthread_mutex_unlock(&out->lock);
5054
5055 /*handles device and call state changes*/
5056 audio_extn_extspk_update(adev->extspk);
5057
5058error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005059 ALOGV("%s: exit: code(%d)", __func__, ret);
5060 return ret;
5061}
5062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5064{
5065 struct stream_out *out = (struct stream_out *)stream;
5066 struct audio_device *adev = out->dev;
5067 struct str_parms *parms;
5068 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005069 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005070 int ext_controller = -1;
5071 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072
sangwoobc677242013-08-08 16:53:43 +09005073 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005074 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005075 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305076 if (!parms)
5077 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005078
5079 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5080 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005081 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005082 out->extconn.cs.controller = ext_controller;
5083 out->extconn.cs.stream = ext_stream;
5084 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5085 use_case_table[out->usecase], out->extconn.cs.controller,
5086 out->extconn.cs.stream);
5087 }
5088
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005089 if (out == adev->primary_output) {
5090 pthread_mutex_lock(&adev->lock);
5091 audio_extn_set_parameters(adev, parms);
5092 pthread_mutex_unlock(&adev->lock);
5093 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005094 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005095 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005096 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005097
5098 audio_extn_dts_create_state_notifier_node(out->usecase);
5099 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5100 popcount(out->channel_mask),
5101 out->playback_started);
5102
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005103 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005104 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005105
Surendar Karkaf51b5842018-04-26 11:28:38 +05305106 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5107 sizeof(value));
5108 if (err >= 0) {
5109 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5110 audio_extn_send_dual_mono_mixing_coefficients(out);
5111 }
5112
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305113 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5114 if (err >= 0) {
5115 strlcpy(out->profile, value, sizeof(out->profile));
5116 ALOGV("updating stream profile with value '%s'", out->profile);
5117 lock_output_stream(out);
5118 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5119 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005120 &out->device_list, out->flags,
5121 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305122 out->sample_rate, out->bit_width,
5123 out->channel_mask, out->profile,
5124 &out->app_type_cfg);
5125 pthread_mutex_unlock(&out->lock);
5126 }
5127
Alexy Joseph98988832017-01-13 14:56:59 -08005128 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005129 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5130 // and vendor.audio.hal.output.suspend.supported is set to true
5131 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005132 //check suspend parameter only for low latency and if the property
5133 //is enabled
5134 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5135 ALOGI("%s: got suspend_playback %s", __func__, value);
5136 lock_output_stream(out);
5137 if (!strncmp(value, "false", 5)) {
5138 //suspend_playback=false is supposed to set QOS value back to 75%
5139 //the mixer control sent with value Enable will achieve that
5140 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5141 } else if (!strncmp (value, "true", 4)) {
5142 //suspend_playback=true is supposed to remove QOS value
5143 //resetting the mixer control will set the default value
5144 //for the mixer control which is Disable and this removes the QOS vote
5145 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5146 } else {
5147 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5148 " got %s", __func__, value);
5149 ret = -1;
5150 }
5151
5152 if (ret != 0) {
5153 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5154 __func__, out->pm_qos_mixer_path, ret);
5155 }
5156
5157 pthread_mutex_unlock(&out->lock);
5158 }
5159 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005160
Alexy Joseph98988832017-01-13 14:56:59 -08005161 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305163error:
Eric Laurent994a6932013-07-17 11:51:42 -07005164 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165 return ret;
5166}
5167
Paul McLeana50b7332018-12-17 08:24:21 -07005168static int in_set_microphone_direction(const struct audio_stream_in *stream,
5169 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005170 struct stream_in *in = (struct stream_in *)stream;
5171
5172 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5173
5174 in->direction = dir;
5175
5176 if (in->standby)
5177 return 0;
5178
5179 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005180}
5181
5182static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005183 struct stream_in *in = (struct stream_in *)stream;
5184
5185 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5186
5187 if (zoom > 1.0 || zoom < -1.0)
5188 return -EINVAL;
5189
5190 in->zoom = zoom;
5191
5192 if (in->standby)
5193 return 0;
5194
5195 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005196}
5197
5198
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005199static bool stream_get_parameter_channels(struct str_parms *query,
5200 struct str_parms *reply,
5201 audio_channel_mask_t *supported_channel_masks) {
5202 int ret = -1;
5203 char value[512];
5204 bool first = true;
5205 size_t i, j;
5206
5207 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5208 ret = 0;
5209 value[0] = '\0';
5210 i = 0;
5211 while (supported_channel_masks[i] != 0) {
5212 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5213 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5214 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305215 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005216
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305217 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005218 first = false;
5219 break;
5220 }
5221 }
5222 i++;
5223 }
5224 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5225 }
5226 return ret == 0;
5227}
5228
5229static bool stream_get_parameter_formats(struct str_parms *query,
5230 struct str_parms *reply,
5231 audio_format_t *supported_formats) {
5232 int ret = -1;
5233 char value[256];
5234 size_t i, j;
5235 bool first = true;
5236
5237 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5238 ret = 0;
5239 value[0] = '\0';
5240 i = 0;
5241 while (supported_formats[i] != 0) {
5242 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5243 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5244 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305245 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005246 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305247 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005248 first = false;
5249 break;
5250 }
5251 }
5252 i++;
5253 }
5254 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5255 }
5256 return ret == 0;
5257}
5258
5259static bool stream_get_parameter_rates(struct str_parms *query,
5260 struct str_parms *reply,
5261 uint32_t *supported_sample_rates) {
5262
5263 int i;
5264 char value[256];
5265 int ret = -1;
5266 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5267 ret = 0;
5268 value[0] = '\0';
5269 i=0;
5270 int cursor = 0;
5271 while (supported_sample_rates[i]) {
5272 int avail = sizeof(value) - cursor;
5273 ret = snprintf(value + cursor, avail, "%s%d",
5274 cursor > 0 ? "|" : "",
5275 supported_sample_rates[i]);
5276 if (ret < 0 || ret >= avail) {
5277 // if cursor is at the last element of the array
5278 // overwrite with \0 is duplicate work as
5279 // snprintf already put a \0 in place.
5280 // else
5281 // we had space to write the '|' at value[cursor]
5282 // (which will be overwritten) or no space to fill
5283 // the first element (=> cursor == 0)
5284 value[cursor] = '\0';
5285 break;
5286 }
5287 cursor += ret;
5288 ++i;
5289 }
5290 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5291 value);
5292 }
5293 return ret >= 0;
5294}
5295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5297{
5298 struct stream_out *out = (struct stream_out *)stream;
5299 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005300 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005301 char value[256];
5302 struct str_parms *reply = str_parms_create();
5303 size_t i, j;
5304 int ret;
5305 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005306
5307 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005308 if (reply) {
5309 str_parms_destroy(reply);
5310 }
5311 if (query) {
5312 str_parms_destroy(query);
5313 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005314 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5315 return NULL;
5316 }
5317
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005318 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5320 if (ret >= 0) {
5321 value[0] = '\0';
5322 i = 0;
5323 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005324 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5325 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005326 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005327 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005328 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005329 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005330 first = false;
5331 break;
5332 }
5333 }
5334 i++;
5335 }
5336 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5337 str = str_parms_to_str(reply);
5338 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005339 voice_extn_out_get_parameters(out, query, reply);
5340 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005341 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005342
Alexy Joseph62142aa2015-11-16 15:10:34 -08005343
5344 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5345 if (ret >= 0) {
5346 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305347 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5348 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005349 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305350 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005351 } else {
5352 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305353 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005354 }
5355 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005356 if (str)
5357 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005358 str = str_parms_to_str(reply);
5359 }
5360
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005361 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5362 if (ret >= 0) {
5363 value[0] = '\0';
5364 i = 0;
5365 first = true;
5366 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005367 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5368 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005369 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005370 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005371 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005372 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005373 first = false;
5374 break;
5375 }
5376 }
5377 i++;
5378 }
5379 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005380 if (str)
5381 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005382 str = str_parms_to_str(reply);
5383 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005384
5385 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5386 if (ret >= 0) {
5387 value[0] = '\0';
5388 i = 0;
5389 first = true;
5390 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005391 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5392 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005393 if (!first) {
5394 strlcat(value, "|", sizeof(value));
5395 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005396 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005397 first = false;
5398 break;
5399 }
5400 }
5401 i++;
5402 }
5403 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5404 if (str)
5405 free(str);
5406 str = str_parms_to_str(reply);
5407 }
5408
Alexy Joseph98988832017-01-13 14:56:59 -08005409 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5410 //only low latency track supports suspend_resume
5411 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005412 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005413 if (str)
5414 free(str);
5415 str = str_parms_to_str(reply);
5416 }
5417
5418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005419 str_parms_destroy(query);
5420 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005421 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422 return str;
5423}
5424
5425static uint32_t out_get_latency(const struct audio_stream_out *stream)
5426{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005427 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005428 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005429 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430
Alexy Josephaa54c872014-12-03 02:46:47 -08005431 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305432 lock_output_stream(out);
5433 latency = audio_extn_utils_compress_get_dsp_latency(out);
5434 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005435 } else if ((out->realtime) ||
5436 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005437 // since the buffer won't be filled up faster than realtime,
5438 // return a smaller number
5439 if (out->config.rate)
5440 period_ms = (out->af_period_multiplier * out->config.period_size *
5441 1000) / (out->config.rate);
5442 else
5443 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005444 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005445 } else {
5446 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005447 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005448 }
5449
Zhou Songd2537a02020-06-11 22:04:46 +08005450 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005451 latency += audio_extn_a2dp_get_encoder_latency();
5452
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305453 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005454 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455}
5456
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305457static float AmpToDb(float amplification)
5458{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305459 float db = DSD_VOLUME_MIN_DB;
5460 if (amplification > 0) {
5461 db = 20 * log10(amplification);
5462 if(db < DSD_VOLUME_MIN_DB)
5463 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305464 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305465 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305466}
5467
Arun Mirpuri5d170872019-03-26 13:21:31 -07005468static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5469 float right)
5470{
5471 struct stream_out *out = (struct stream_out *)stream;
5472 long volume = 0;
5473 char mixer_ctl_name[128] = "";
5474 struct audio_device *adev = out->dev;
5475 struct mixer_ctl *ctl = NULL;
5476 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5477 PCM_PLAYBACK);
5478
5479 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5480 "Playback %d Volume", pcm_device_id);
5481 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5482 if (!ctl) {
5483 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5484 __func__, mixer_ctl_name);
5485 return -EINVAL;
5486 }
5487 if (left != right)
5488 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5489 __func__, left, right);
5490 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5491 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5492 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5493 __func__, mixer_ctl_name, volume);
5494 return -EINVAL;
5495 }
5496 return 0;
5497}
5498
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305499static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5500 float right)
5501{
5502 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305503 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305504 char mixer_ctl_name[128];
5505 struct audio_device *adev = out->dev;
5506 struct mixer_ctl *ctl;
5507 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5508 PCM_PLAYBACK);
5509
5510 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5511 "Compress Playback %d Volume", pcm_device_id);
5512 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5513 if (!ctl) {
5514 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5515 __func__, mixer_ctl_name);
5516 return -EINVAL;
5517 }
5518 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5519 __func__, mixer_ctl_name, left, right);
5520 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5521 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5522 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5523
5524 return 0;
5525}
5526
Zhou Song2b8f28f2017-09-11 10:51:38 +08005527static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5528 float right)
5529{
5530 struct stream_out *out = (struct stream_out *)stream;
5531 char mixer_ctl_name[] = "App Type Gain";
5532 struct audio_device *adev = out->dev;
5533 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305534 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005535
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005536 if (!is_valid_volume(left, right)) {
5537 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5538 __func__, left, right);
5539 return -EINVAL;
5540 }
5541
Zhou Song2b8f28f2017-09-11 10:51:38 +08005542 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5543 if (!ctl) {
5544 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5545 __func__, mixer_ctl_name);
5546 return -EINVAL;
5547 }
5548
5549 set_values[0] = 0; //0: Rx Session 1:Tx Session
5550 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305551 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5552 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005553
5554 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5555 return 0;
5556}
5557
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305558static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5559 float right)
5560{
5561 struct stream_out *out = (struct stream_out *)stream;
5562 /* Volume control for pcm playback */
5563 if (left != right) {
5564 return -EINVAL;
5565 } else {
5566 char mixer_ctl_name[128];
5567 struct audio_device *adev = out->dev;
5568 struct mixer_ctl *ctl;
5569 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5570 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5571 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5572 if (!ctl) {
5573 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5574 return -EINVAL;
5575 }
5576
5577 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5578 int ret = mixer_ctl_set_value(ctl, 0, volume);
5579 if (ret < 0) {
5580 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5581 return -EINVAL;
5582 }
5583
5584 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5585
5586 return 0;
5587 }
5588}
5589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590static int out_set_volume(struct audio_stream_out *stream, float left,
5591 float right)
5592{
Eric Laurenta9024de2013-04-04 09:19:12 -07005593 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005594 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305595 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005596
Arun Mirpuri5d170872019-03-26 13:21:31 -07005597 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005598 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5599 /* only take left channel into account: the API is for stereo anyway */
5600 out->muted = (left == 0.0f);
5601 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005602 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305603 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005604 /*
5605 * Set mute or umute on HDMI passthrough stream.
5606 * Only take left channel into account.
5607 * Mute is 0 and unmute 1
5608 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305609 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305610 } else if (out->format == AUDIO_FORMAT_DSD){
5611 char mixer_ctl_name[128] = "DSD Volume";
5612 struct audio_device *adev = out->dev;
5613 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5614
5615 if (!ctl) {
5616 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5617 __func__, mixer_ctl_name);
5618 return -EINVAL;
5619 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305620 volume[0] = (long)(AmpToDb(left));
5621 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305622 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5623 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005624 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005625 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005626 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5627 struct listnode *node = NULL;
5628 list_for_each(node, &adev->active_outputs_list) {
5629 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5630 streams_output_ctxt_t,
5631 list);
5632 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5633 out->volume_l = out_ctxt->output->volume_l;
5634 out->volume_r = out_ctxt->output->volume_r;
5635 }
5636 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005637 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005638 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005639 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5640 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005641 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005642 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005643 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005644 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005645 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5646 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305647 ret = out_set_compr_volume(stream, left, right);
5648 out->volume_l = left;
5649 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005650 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305651 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005652 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005653 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005654 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5655 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005656 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005657 if (!out->standby) {
5658 audio_extn_utils_send_app_type_gain(out->dev,
5659 out->app_type_cfg.app_type,
5660 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005661 if (!out->a2dp_muted)
5662 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005663 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005664 out->volume_l = left;
5665 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005666 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005667 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005668 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5669 ALOGV("%s: MMAP set volume called", __func__);
5670 if (!out->standby)
5671 ret = out_set_mmap_volume(stream, left, right);
5672 out->volume_l = left;
5673 out->volume_r = right;
5674 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305675 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305676 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5677 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005678 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305679 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005680 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305681 ret = out_set_pcm_volume(stream, left, right);
5682 else
5683 out->apply_volume = true;
5684
5685 out->volume_l = left;
5686 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005687 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305688 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005689 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5690 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005691 pthread_mutex_lock(&out->latch_lock);
5692 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005693 ret = out_set_pcm_volume(stream, left, right);
5694 out->volume_l = left;
5695 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005696 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005697 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005698 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700 return -ENOSYS;
5701}
5702
Zhou Songc9672822017-08-16 16:01:39 +08005703static void update_frames_written(struct stream_out *out, size_t bytes)
5704{
5705 size_t bpf = 0;
5706
5707 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5708 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5709 bpf = 1;
5710 else if (!is_offload_usecase(out->usecase))
5711 bpf = audio_bytes_per_sample(out->format) *
5712 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005713
5714 pthread_mutex_lock(&out->position_query_lock);
5715 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005716 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005717 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5718 }
5719 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005720}
5721
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005722int split_and_write_audio_haptic_data(struct stream_out *out,
5723 const void *buffer, size_t bytes_to_write)
5724{
5725 struct audio_device *adev = out->dev;
5726
5727 int ret = 0;
5728 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5729 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5730 size_t frame_size = channel_count * bytes_per_sample;
5731 size_t frame_count = bytes_to_write / frame_size;
5732
5733 bool force_haptic_path =
5734 property_get_bool("vendor.audio.test_haptic", false);
5735
5736 // extract Haptics data from Audio buffer
5737 bool alloc_haptic_buffer = false;
5738 int haptic_channel_count = adev->haptics_config.channels;
5739 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5740 size_t audio_frame_size = frame_size - haptic_frame_size;
5741 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5742
5743 if (adev->haptic_buffer == NULL) {
5744 alloc_haptic_buffer = true;
5745 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5746 free(adev->haptic_buffer);
5747 adev->haptic_buffer_size = 0;
5748 alloc_haptic_buffer = true;
5749 }
5750
5751 if (alloc_haptic_buffer) {
5752 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005753 if(adev->haptic_buffer == NULL) {
5754 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5755 return -ENOMEM;
5756 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005757 adev->haptic_buffer_size = total_haptic_buffer_size;
5758 }
5759
5760 size_t src_index = 0, aud_index = 0, hap_index = 0;
5761 uint8_t *audio_buffer = (uint8_t *)buffer;
5762 uint8_t *haptic_buffer = adev->haptic_buffer;
5763
5764 // This is required for testing only. This works for stereo data only.
5765 // One channel is fed to audio stream and other to haptic stream for testing.
5766 if (force_haptic_path)
5767 audio_frame_size = haptic_frame_size = bytes_per_sample;
5768
5769 for (size_t i = 0; i < frame_count; i++) {
5770 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5771 audio_frame_size);
5772 aud_index += audio_frame_size;
5773 src_index += audio_frame_size;
5774
5775 if (adev->haptic_pcm)
5776 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5777 haptic_frame_size);
5778 hap_index += haptic_frame_size;
5779 src_index += haptic_frame_size;
5780
5781 // This is required for testing only.
5782 // Discard haptic channel data.
5783 if (force_haptic_path)
5784 src_index += haptic_frame_size;
5785 }
5786
5787 // write to audio pipeline
5788 ret = pcm_write(out->pcm, (void *)audio_buffer,
5789 frame_count * audio_frame_size);
5790
5791 // write to haptics pipeline
5792 if (adev->haptic_pcm)
5793 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5794 frame_count * haptic_frame_size);
5795
5796 return ret;
5797}
5798
Aalique Grahame22e49102018-12-18 14:23:57 -08005799#ifdef NO_AUDIO_OUT
5800static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5801 const void *buffer __unused, size_t bytes)
5802{
5803 struct stream_out *out = (struct stream_out *)stream;
5804
5805 /* No Output device supported other than BT for playback.
5806 * Sleep for the amount of buffer duration
5807 */
5808 lock_output_stream(out);
5809 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5810 (const struct audio_stream_out *)&out->stream) /
5811 out_get_sample_rate(&out->stream.common));
5812 pthread_mutex_unlock(&out->lock);
5813 return bytes;
5814}
5815#endif
5816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005817static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5818 size_t bytes)
5819{
5820 struct stream_out *out = (struct stream_out *)stream;
5821 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005822 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305823 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005824 const size_t frame_size = audio_stream_out_frame_size(stream);
5825 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305826 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005827 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005828
Haynes Mathew George380745d2017-10-04 15:27:45 -07005829 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005830 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305831
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305832 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005833
Dhananjay Kumarac341582017-02-23 23:42:25 +05305834 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305835 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305836 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5837 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005838 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305839 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305840 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305841 ALOGD(" %s: sound card is not active/SSR state", __func__);
5842 ret= -EIO;
5843 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305844 }
5845 }
5846
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305847 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305848 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305849 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305850 goto exit;
5851 }
5852
Haynes Mathew George16081042017-05-31 17:16:49 -07005853 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5854 ret = -EINVAL;
5855 goto exit;
5856 }
5857
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005858 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305859 !out->is_iec61937_info_available) {
5860
5861 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5862 out->is_iec61937_info_available = true;
5863 } else if (audio_extn_passthru_is_enabled()) {
5864 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305865 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305866
5867 if((out->format == AUDIO_FORMAT_DTS) ||
5868 (out->format == AUDIO_FORMAT_DTS_HD)) {
5869 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5870 buffer, bytes);
5871 if (ret) {
5872 if (ret != -ENOSYS) {
5873 out->is_iec61937_info_available = false;
5874 ALOGD("iec61937 transmission info not yet updated retry");
5875 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305876 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305877 /* if stream has started and after that there is
5878 * stream config change (iec transmission config)
5879 * then trigger select_device to update backend configuration.
5880 */
5881 out->stream_config_changed = true;
5882 pthread_mutex_lock(&adev->lock);
5883 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305884 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005885 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305886 ret = -EINVAL;
5887 goto exit;
5888 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305889 pthread_mutex_unlock(&adev->lock);
5890 out->stream_config_changed = false;
5891 out->is_iec61937_info_available = true;
5892 }
5893 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305894
Meng Wang4c32fb42020-01-16 17:57:11 +08005895#ifdef AUDIO_GKI_ENABLED
5896 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5897 compr_passthr = out->compr_config.codec->reserved[0];
5898#else
5899 compr_passthr = out->compr_config.codec->compr_passthr;
5900#endif
5901
Garmond Leung317cbf12017-09-13 16:20:50 -07005902 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005903 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305904 (out->is_iec61937_info_available == true)) {
5905 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5906 ret = -EINVAL;
5907 goto exit;
5908 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305909 }
5910 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305911
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005912 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005913 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005914 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5915 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005916 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305917 ret = -EIO;
5918 goto exit;
5919 }
5920 }
5921 }
5922
Weiyin Jiangabedea32020-12-09 12:49:19 +08005923 if (is_usb_out_device_type(&out->device_list) &&
5924 !audio_extn_usb_connected(NULL)) {
5925 ret = -EIO;
5926 goto exit;
5927 }
5928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005929 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005930 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005931 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5932
Eric Laurent150dbfe2013-02-27 14:31:02 -08005933 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005934 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5935 ret = voice_extn_compress_voip_start_output_stream(out);
5936 else
5937 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005938 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005939 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005940 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005941 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005942 goto exit;
5943 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305944 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005945 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005946
5947 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005948 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005949 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305950 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005951 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005952 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305953
5954 if ((out->is_iec61937_info_available == true) &&
5955 (audio_extn_passthru_is_passthrough_stream(out))&&
5956 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5957 ret = -EINVAL;
5958 goto exit;
5959 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305960 if (out->set_dual_mono)
5961 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005962
5963 // log startup time in ms.
5964 simple_stats_log(
5965 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005966 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005967
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005968 if (adev->is_channel_status_set == false &&
5969 compare_device_type(&out->device_list,
5970 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005971 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305972 adev->is_channel_status_set = true;
5973 }
5974
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305975 if ((adev->use_old_pspd_mix_ctrl == true) &&
5976 (out->pspd_coeff_sent == false)) {
5977 /*
5978 * Need to resend pspd coefficients after stream started for
5979 * older kernel version as it does not save the coefficients
5980 * and also stream has to be started for coeff to apply.
5981 */
5982 usecase = get_usecase_from_list(adev, out->usecase);
5983 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305984 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305985 out->pspd_coeff_sent = true;
5986 }
5987 }
5988
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005989 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005990 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005991 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005992 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005993 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5994 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305995 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5996 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005997 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305998 out->send_next_track_params = false;
5999 out->is_compr_metadata_avail = false;
6000 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006001 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306002 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306003 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006004
Ashish Jain83a6cc22016-06-28 14:34:17 +05306005 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306006 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306007 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306008 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006009 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306010 return -EINVAL;
6011 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306012 audio_format_t dst_format = out->hal_op_format;
6013 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306014
Dieter Luecking5d57def2018-09-07 14:23:37 +02006015 /* prevent division-by-zero */
6016 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6017 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6018 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6019 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306020 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006021 ATRACE_END();
6022 return -EINVAL;
6023 }
6024
Ashish Jainf1eaa582016-05-23 20:54:24 +05306025 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6026 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6027
Ashish Jain83a6cc22016-06-28 14:34:17 +05306028 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306029 dst_format,
6030 buffer,
6031 src_format,
6032 frames);
6033
Ashish Jain83a6cc22016-06-28 14:34:17 +05306034 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306035 bytes_to_write);
6036
6037 /*Convert written bytes in audio flinger format*/
6038 if (ret > 0)
6039 ret = ((ret * format_to_bitwidth_table[out->format]) /
6040 format_to_bitwidth_table[dst_format]);
6041 }
6042 } else
6043 ret = compress_write(out->compr, buffer, bytes);
6044
Zhou Songc9672822017-08-16 16:01:39 +08006045 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6046 update_frames_written(out, bytes);
6047
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306048 if (ret < 0)
6049 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006050 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306051 /*msg to cb thread only if non blocking write is enabled*/
6052 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306053 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006054 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306055 } else if (-ENETRESET == ret) {
6056 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306057 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306058 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306059 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006060 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306061 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006062 }
Ashish Jain5106d362016-05-11 19:23:33 +05306063
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306064 /* Call compr start only when non-zero bytes of data is there to be rendered */
6065 if (!out->playback_started && ret > 0) {
6066 int status = compress_start(out->compr);
6067 if (status < 0) {
6068 ret = status;
6069 ALOGE("%s: compr start failed with err %d", __func__, errno);
6070 goto exit;
6071 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006072 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006073 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006074 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006075 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006076 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006077
6078 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6079 popcount(out->channel_mask),
6080 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006081 }
6082 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006083 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006084 return ret;
6085 } else {
6086 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006087 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006088 if (out->muted)
6089 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006090 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6091 __func__, frames, frame_size, bytes_to_write);
6092
Aalique Grahame22e49102018-12-18 14:23:57 -08006093 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006094 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6095 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6096 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006097 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6098 int16_t *src = (int16_t *)buffer;
6099 int16_t *dst = (int16_t *)buffer;
6100
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006101 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006102 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006103 "out_write called for %s use case with wrong properties",
6104 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006105
6106 /*
6107 * FIXME: this can be removed once audio flinger mixer supports
6108 * mono output
6109 */
6110
6111 /*
6112 * Code below goes over each frame in the buffer and adds both
6113 * L and R samples and then divides by 2 to convert to mono
6114 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006115 if (channel_count == 2) {
6116 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6117 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6118 }
6119 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006120 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006121 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006122
6123 // Note: since out_get_presentation_position() is called alternating with out_write()
6124 // by AudioFlinger, we can check underruns using the prior timestamp read.
6125 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6126 if (out->last_fifo_valid) {
6127 // compute drain to see if there is an underrun.
6128 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306129 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6130 int64_t frames_by_time =
6131 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6132 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006133 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6134
6135 if (underrun > 0) {
6136 simple_stats_log(&out->fifo_underruns, underrun);
6137
6138 ALOGW("%s: underrun(%lld) "
6139 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6140 __func__,
6141 (long long)out->fifo_underruns.n,
6142 (long long)frames_by_time,
6143 (long long)out->last_fifo_frames_remaining);
6144 }
6145 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6146 }
6147
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306148 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006149
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006150 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006151
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006152 if (out->config.rate)
6153 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6154 out->config.rate;
6155
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006156 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006157 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6158
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006159 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006160 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006161 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306162 out->convert_buffer != NULL) {
6163
6164 memcpy_by_audio_format(out->convert_buffer,
6165 out->hal_op_format,
6166 buffer,
6167 out->hal_ip_format,
6168 out->config.period_size * out->config.channels);
6169
6170 ret = pcm_write(out->pcm, out->convert_buffer,
6171 (out->config.period_size *
6172 out->config.channels *
6173 format_to_bitwidth_table[out->hal_op_format]));
6174 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306175 /*
6176 * To avoid underrun in DSP when the application is not pumping
6177 * data at required rate, check for the no. of bytes and ignore
6178 * pcm_write if it is less than actual buffer size.
6179 * It is a work around to a change in compress VOIP driver.
6180 */
6181 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6182 bytes < (out->config.period_size * out->config.channels *
6183 audio_bytes_per_sample(out->format))) {
6184 size_t voip_buf_size =
6185 out->config.period_size * out->config.channels *
6186 audio_bytes_per_sample(out->format);
6187 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6188 __func__, bytes, voip_buf_size);
6189 usleep(((uint64_t)voip_buf_size - bytes) *
6190 1000000 / audio_stream_out_frame_size(stream) /
6191 out_get_sample_rate(&out->stream.common));
6192 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006193 } else {
6194 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6195 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6196 else
6197 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6198 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306199 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006200
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006201 release_out_focus(out);
6202
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306203 if (ret < 0)
6204 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006205 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306206 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006208 }
6209
6210exit:
Zhou Songc9672822017-08-16 16:01:39 +08006211 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306212 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306213 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006215 pthread_mutex_unlock(&out->lock);
6216
6217 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006218 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006219 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306220 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306221 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306222 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306223 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306224 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306225 out->standby = true;
6226 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306227 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006228 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6229 /* prevent division-by-zero */
6230 uint32_t stream_size = audio_stream_out_frame_size(stream);
6231 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006232
Dieter Luecking5d57def2018-09-07 14:23:37 +02006233 if ((stream_size == 0) || (srate == 0)) {
6234 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6235 ATRACE_END();
6236 return -EINVAL;
6237 }
6238 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6239 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006240 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306241 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006242 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006243 return ret;
6244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006245 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006246 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006247 return bytes;
6248}
6249
6250static int out_get_render_position(const struct audio_stream_out *stream,
6251 uint32_t *dsp_frames)
6252{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006253 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006254
6255 if (dsp_frames == NULL)
6256 return -EINVAL;
6257
6258 *dsp_frames = 0;
6259 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006260 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306261
6262 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6263 * this operation and adev_close_output_stream(where out gets reset).
6264 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306265 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006266 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306267 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006268 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306269 return 0;
6270 }
6271
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006272 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306273 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306274 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006275 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306276 if (ret < 0)
6277 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006278 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306279 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006280 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306281 if (-ENETRESET == ret) {
6282 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306283 out->card_status = CARD_STATUS_OFFLINE;
6284 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306285 } else if(ret < 0) {
6286 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306287 ret = -EINVAL;
6288 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306289 /*
6290 * Handle corner case where compress session is closed during SSR
6291 * and timestamp is queried
6292 */
6293 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306294 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306295 } else if (out->prev_card_status_offline) {
6296 ALOGE("ERROR: previously sound card was offline,return error");
6297 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306298 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306299 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006300 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306301 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306302 pthread_mutex_unlock(&out->lock);
6303 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006304 } else if (audio_is_linear_pcm(out->format)) {
6305 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006306 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006307 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006308 } else
6309 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006310}
6311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006312static int out_add_audio_effect(const struct audio_stream *stream __unused,
6313 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006314{
6315 return 0;
6316}
6317
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006318static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6319 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006320{
6321 return 0;
6322}
6323
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006324static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6325 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006326{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306327 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006328}
6329
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006330static int out_get_presentation_position(const struct audio_stream_out *stream,
6331 uint64_t *frames, struct timespec *timestamp)
6332{
6333 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306334 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006335 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006336
Ashish Jain5106d362016-05-11 19:23:33 +05306337 /* below piece of code is not guarded against any lock because audioFliner serializes
6338 * this operation and adev_close_output_stream( where out gets reset).
6339 */
6340 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306341 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006342 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306343 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6344 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6345 return 0;
6346 }
6347
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006348 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006349
Ashish Jain5106d362016-05-11 19:23:33 +05306350 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6351 ret = compress_get_tstamp(out->compr, &dsp_frames,
6352 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006353 // Adjustment accounts for A2dp encoder latency with offload usecases
6354 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006355 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006356 unsigned long offset =
6357 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6358 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6359 }
Ashish Jain5106d362016-05-11 19:23:33 +05306360 ALOGVV("%s rendered frames %ld sample_rate %d",
6361 __func__, dsp_frames, out->sample_rate);
6362 *frames = dsp_frames;
6363 if (ret < 0)
6364 ret = -errno;
6365 if (-ENETRESET == ret) {
6366 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306367 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306368 ret = -EINVAL;
6369 } else
6370 ret = 0;
6371 /* this is the best we can do */
6372 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006373 } else {
6374 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006375 unsigned int avail;
6376 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006377 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006378 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006379
Andy Hunga1f48fa2019-07-01 18:14:53 -07006380 if (out->kernel_buffer_size > avail) {
6381 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6382 } else {
6383 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6384 __func__, avail, out->kernel_buffer_size);
6385 avail = out->kernel_buffer_size;
6386 frames_temp = out->last_fifo_frames_remaining = 0;
6387 }
6388 out->last_fifo_valid = true;
6389 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6390
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006391 if (out->written >= frames_temp)
6392 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006393
Andy Hunga1f48fa2019-07-01 18:14:53 -07006394 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6395 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6396
Weiyin Jiangd4633762018-03-16 12:05:03 +08006397 // This adjustment accounts for buffering after app processor.
6398 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006399 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006400 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006401 if (signed_frames >= frames_temp)
6402 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006403
Weiyin Jiangd4633762018-03-16 12:05:03 +08006404 // Adjustment accounts for A2dp encoder latency with non offload usecases
6405 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006406 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006407 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6408 if (signed_frames >= frames_temp)
6409 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006410 }
6411
6412 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006413 *frames = signed_frames;
6414 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006415 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006416 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6417 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006418 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306419 *frames = out->written;
6420 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306421 if (is_offload_usecase(out->usecase))
6422 ret = -EINVAL;
6423 else
6424 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006425 }
6426 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006427 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006428 return ret;
6429}
6430
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006431static int out_set_callback(struct audio_stream_out *stream,
6432 stream_callback_t callback, void *cookie)
6433{
6434 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006435 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006436
6437 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006438 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006439 out->client_callback = callback;
6440 out->client_cookie = cookie;
6441 if (out->adsp_hdlr_stream_handle) {
6442 ret = audio_extn_adsp_hdlr_stream_set_callback(
6443 out->adsp_hdlr_stream_handle,
6444 callback,
6445 cookie);
6446 if (ret)
6447 ALOGW("%s:adsp hdlr callback registration failed %d",
6448 __func__, ret);
6449 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006450 pthread_mutex_unlock(&out->lock);
6451 return 0;
6452}
6453
6454static int out_pause(struct audio_stream_out* stream)
6455{
6456 struct stream_out *out = (struct stream_out *)stream;
6457 int status = -ENOSYS;
6458 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006459 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006460 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306461 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006462 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006463 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006464 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306465 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306466 status = compress_pause(out->compr);
6467
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006468 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006469
Mingming Yin21854652016-04-13 11:54:02 -07006470 if (audio_extn_passthru_is_active()) {
6471 ALOGV("offload use case, pause passthru");
6472 audio_extn_passthru_on_pause(out);
6473 }
6474
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306475 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006476 audio_extn_dts_notify_playback_state(out->usecase, 0,
6477 out->sample_rate, popcount(out->channel_mask),
6478 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006479 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006480 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006481 pthread_mutex_unlock(&out->lock);
6482 }
6483 return status;
6484}
6485
6486static int out_resume(struct audio_stream_out* stream)
6487{
6488 struct stream_out *out = (struct stream_out *)stream;
6489 int status = -ENOSYS;
6490 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006491 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006492 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306493 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006494 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006495 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006496 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306497 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306498 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006499 }
6500 if (!status) {
6501 out->offload_state = OFFLOAD_STATE_PLAYING;
6502 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306503 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006504 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6505 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006506 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006507 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006508 pthread_mutex_unlock(&out->lock);
6509 }
6510 return status;
6511}
6512
6513static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6514{
6515 struct stream_out *out = (struct stream_out *)stream;
6516 int status = -ENOSYS;
6517 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006518 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006519 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006520 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6521 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6522 else
6523 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6524 pthread_mutex_unlock(&out->lock);
6525 }
6526 return status;
6527}
6528
6529static int out_flush(struct audio_stream_out* stream)
6530{
6531 struct stream_out *out = (struct stream_out *)stream;
6532 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006533 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006534 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006535 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006536 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006537 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306538 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006539 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006540 } else {
6541 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306542 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006543 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006544 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006545 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006546 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006547 return 0;
6548 }
6549 return -ENOSYS;
6550}
6551
Haynes Mathew George16081042017-05-31 17:16:49 -07006552static int out_stop(const struct audio_stream_out* stream)
6553{
6554 struct stream_out *out = (struct stream_out *)stream;
6555 struct audio_device *adev = out->dev;
6556 int ret = -ENOSYS;
6557
6558 ALOGV("%s", __func__);
6559 pthread_mutex_lock(&adev->lock);
6560 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6561 out->playback_started && out->pcm != NULL) {
6562 pcm_stop(out->pcm);
6563 ret = stop_output_stream(out);
6564 out->playback_started = false;
6565 }
6566 pthread_mutex_unlock(&adev->lock);
6567 return ret;
6568}
6569
6570static int out_start(const struct audio_stream_out* stream)
6571{
6572 struct stream_out *out = (struct stream_out *)stream;
6573 struct audio_device *adev = out->dev;
6574 int ret = -ENOSYS;
6575
6576 ALOGV("%s", __func__);
6577 pthread_mutex_lock(&adev->lock);
6578 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6579 !out->playback_started && out->pcm != NULL) {
6580 ret = start_output_stream(out);
6581 if (ret == 0) {
6582 out->playback_started = true;
6583 }
6584 }
6585 pthread_mutex_unlock(&adev->lock);
6586 return ret;
6587}
6588
6589/*
6590 * Modify config->period_count based on min_size_frames
6591 */
6592static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6593{
6594 int periodCountRequested = (min_size_frames + config->period_size - 1)
6595 / config->period_size;
6596 int periodCount = MMAP_PERIOD_COUNT_MIN;
6597
6598 ALOGV("%s original config.period_size = %d config.period_count = %d",
6599 __func__, config->period_size, config->period_count);
6600
6601 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6602 periodCount *= 2;
6603 }
6604 config->period_count = periodCount;
6605
6606 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6607}
6608
Phil Burkfe17efd2019-03-25 10:23:35 -07006609// Read offset for the positional timestamp from a persistent vendor property.
6610// This is to workaround apparent inaccuracies in the timing information that
6611// is used by the AAudio timing model. The inaccuracies can cause glitches.
6612static int64_t get_mmap_out_time_offset() {
6613 const int32_t kDefaultOffsetMicros = 0;
6614 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006615 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006616 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6617 return mmap_time_offset_micros * (int64_t)1000;
6618}
6619
Haynes Mathew George16081042017-05-31 17:16:49 -07006620static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6621 int32_t min_size_frames,
6622 struct audio_mmap_buffer_info *info)
6623{
6624 struct stream_out *out = (struct stream_out *)stream;
6625 struct audio_device *adev = out->dev;
6626 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006627 unsigned int offset1 = 0;
6628 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006629 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006630 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006631 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006632
Arun Mirpuri5d170872019-03-26 13:21:31 -07006633 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306634 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006635 pthread_mutex_lock(&adev->lock);
6636
Sharad Sanglec6f32552018-05-04 16:15:38 +05306637 if (CARD_STATUS_OFFLINE == out->card_status ||
6638 CARD_STATUS_OFFLINE == adev->card_status) {
6639 ALOGW("out->card_status or adev->card_status offline, try again");
6640 ret = -EIO;
6641 goto exit;
6642 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306643 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006644 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6645 ret = -EINVAL;
6646 goto exit;
6647 }
6648 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6649 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6650 ret = -ENOSYS;
6651 goto exit;
6652 }
6653 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6654 if (out->pcm_device_id < 0) {
6655 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6656 __func__, out->pcm_device_id, out->usecase);
6657 ret = -EINVAL;
6658 goto exit;
6659 }
6660
6661 adjust_mmap_period_count(&out->config, min_size_frames);
6662
Arun Mirpuri5d170872019-03-26 13:21:31 -07006663 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006664 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6665 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6666 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306667 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306668 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6669 out->card_status = CARD_STATUS_OFFLINE;
6670 adev->card_status = CARD_STATUS_OFFLINE;
6671 ret = -EIO;
6672 goto exit;
6673 }
6674
Haynes Mathew George16081042017-05-31 17:16:49 -07006675 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6676 step = "open";
6677 ret = -ENODEV;
6678 goto exit;
6679 }
6680 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6681 if (ret < 0) {
6682 step = "begin";
6683 goto exit;
6684 }
juyuchen626833d2019-06-04 16:48:02 +08006685
6686 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006687 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006688 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006689 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006690 ret = platform_get_mmap_data_fd(adev->platform,
6691 out->pcm_device_id, 0 /*playback*/,
6692 &info->shared_memory_fd,
6693 &mmap_size);
6694 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006695 // Fall back to non exclusive mode
6696 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6697 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006698 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6699 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6700
Arun Mirpuri5d170872019-03-26 13:21:31 -07006701 if (mmap_size < buffer_size) {
6702 step = "mmap";
6703 goto exit;
6704 }
juyuchen626833d2019-06-04 16:48:02 +08006705 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006706 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006707 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006708 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006709
6710 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6711 if (ret < 0) {
6712 step = "commit";
6713 goto exit;
6714 }
6715
Phil Burkfe17efd2019-03-25 10:23:35 -07006716 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6717
Haynes Mathew George16081042017-05-31 17:16:49 -07006718 out->standby = false;
6719 ret = 0;
6720
Arun Mirpuri5d170872019-03-26 13:21:31 -07006721 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006722 __func__, info->shared_memory_address, info->buffer_size_frames);
6723
6724exit:
6725 if (ret != 0) {
6726 if (out->pcm == NULL) {
6727 ALOGE("%s: %s - %d", __func__, step, ret);
6728 } else {
6729 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6730 pcm_close(out->pcm);
6731 out->pcm = NULL;
6732 }
6733 }
6734 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306735 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006736 return ret;
6737}
6738
6739static int out_get_mmap_position(const struct audio_stream_out *stream,
6740 struct audio_mmap_position *position)
6741{
6742 struct stream_out *out = (struct stream_out *)stream;
6743 ALOGVV("%s", __func__);
6744 if (position == NULL) {
6745 return -EINVAL;
6746 }
6747 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006748 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006749 return -ENOSYS;
6750 }
6751 if (out->pcm == NULL) {
6752 return -ENOSYS;
6753 }
6754
6755 struct timespec ts = { 0, 0 };
6756 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6757 if (ret < 0) {
6758 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6759 return ret;
6760 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006761 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6762 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006763 return 0;
6764}
6765
6766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006767/** audio_stream_in implementation **/
6768static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6769{
6770 struct stream_in *in = (struct stream_in *)stream;
6771
6772 return in->config.rate;
6773}
6774
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006775static int in_set_sample_rate(struct audio_stream *stream __unused,
6776 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006777{
6778 return -ENOSYS;
6779}
6780
6781static size_t in_get_buffer_size(const struct audio_stream *stream)
6782{
6783 struct stream_in *in = (struct stream_in *)stream;
6784
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006785 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6786 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006787 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6788 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306789 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306790 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006791
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006792 return in->config.period_size * in->af_period_multiplier *
6793 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006794}
6795
6796static uint32_t in_get_channels(const struct audio_stream *stream)
6797{
6798 struct stream_in *in = (struct stream_in *)stream;
6799
6800 return in->channel_mask;
6801}
6802
6803static audio_format_t in_get_format(const struct audio_stream *stream)
6804{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006805 struct stream_in *in = (struct stream_in *)stream;
6806
6807 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006808}
6809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006810static int in_set_format(struct audio_stream *stream __unused,
6811 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006812{
6813 return -ENOSYS;
6814}
6815
6816static int in_standby(struct audio_stream *stream)
6817{
6818 struct stream_in *in = (struct stream_in *)stream;
6819 struct audio_device *adev = in->dev;
6820 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306821 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6822 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006823 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306824
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006825 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006826 if (!in->standby && in->is_st_session) {
6827 ALOGD("%s: sound trigger pcm stop lab", __func__);
6828 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006829 if (adev->num_va_sessions > 0)
6830 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006831 in->standby = 1;
6832 }
6833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006834 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006835 if (adev->adm_deregister_stream)
6836 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6837
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006838 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006839 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006840 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006841 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006842 voice_extn_compress_voip_close_input_stream(stream);
6843 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006844 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6845 do_stop = in->capture_started;
6846 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006847 if (in->mmap_shared_memory_fd >= 0) {
6848 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6849 __func__, in->mmap_shared_memory_fd);
6850 close(in->mmap_shared_memory_fd);
6851 in->mmap_shared_memory_fd = -1;
6852 }
Zhou Songa8895042016-07-05 17:54:22 +08006853 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306854 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306855 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006856 }
6857
Arun Mirpuri5d170872019-03-26 13:21:31 -07006858 if (in->pcm) {
6859 ATRACE_BEGIN("pcm_in_close");
6860 pcm_close(in->pcm);
6861 ATRACE_END();
6862 in->pcm = NULL;
6863 }
6864
Carter Hsu2e429db2019-05-14 18:50:52 +08006865 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006866 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006867
George Gao3018ede2019-10-23 13:23:00 -07006868 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6869 if (adev->num_va_sessions > 0)
6870 adev->num_va_sessions--;
6871 }
Quinn Malef6050362019-01-30 15:55:40 -08006872
Eric Laurent150dbfe2013-02-27 14:31:02 -08006873 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006874 }
6875 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006876 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 return status;
6878}
6879
Aalique Grahame22e49102018-12-18 14:23:57 -08006880static int in_dump(const struct audio_stream *stream,
6881 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006882{
Aalique Grahame22e49102018-12-18 14:23:57 -08006883 struct stream_in *in = (struct stream_in *)stream;
6884
6885 // We try to get the lock for consistency,
6886 // but it isn't necessary for these variables.
6887 // If we're not in standby, we may be blocked on a read.
6888 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6889 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6890 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6891 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6892
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006893 char buffer[256]; // for statistics formatting
6894 if (in->start_latency_ms.n > 0) {
6895 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6896 dprintf(fd, " Start latency ms: %s\n", buffer);
6897 }
6898
Aalique Grahame22e49102018-12-18 14:23:57 -08006899 if (locked) {
6900 pthread_mutex_unlock(&in->lock);
6901 }
6902
6903 // dump error info
6904 (void)error_log_dump(
6905 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006907 return 0;
6908}
6909
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306910static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6911{
6912 if (!stream || !parms)
6913 return;
6914
6915 struct stream_in *in = (struct stream_in *)stream;
6916 struct audio_device *adev = in->dev;
6917
6918 card_status_t status;
6919 int card;
6920 if (parse_snd_card_status(parms, &card, &status) < 0)
6921 return;
6922
6923 pthread_mutex_lock(&adev->lock);
6924 bool valid_cb = (card == adev->snd_card);
6925 pthread_mutex_unlock(&adev->lock);
6926
6927 if (!valid_cb)
6928 return;
6929
6930 lock_input_stream(in);
6931 if (in->card_status != status)
6932 in->card_status = status;
6933 pthread_mutex_unlock(&in->lock);
6934
6935 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6936 use_case_table[in->usecase],
6937 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6938
6939 // a better solution would be to report error back to AF and let
6940 // it put the stream to standby
6941 if (status == CARD_STATUS_OFFLINE)
6942 in_standby(&in->stream.common);
6943
6944 return;
6945}
6946
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006947int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006948 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006949 audio_source_t source)
6950{
6951 struct audio_device *adev = in->dev;
6952 int ret = 0;
6953
6954 lock_input_stream(in);
6955 pthread_mutex_lock(&adev->lock);
6956
6957 /* no audio source uses val == 0 */
6958 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6959 in->source = source;
6960 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6961 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6962 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6963 (in->config.rate == 8000 || in->config.rate == 16000 ||
6964 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6965 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6966 ret = voice_extn_compress_voip_open_input_stream(in);
6967 if (ret != 0) {
6968 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6969 __func__, ret);
6970 }
6971 }
6972 }
6973
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006974 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6975 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006976 // Workaround: If routing to an non existing usb device, fail gracefully
6977 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006978 struct str_parms *usb_addr =
6979 str_parms_create_str(get_usb_device_address(devices));
6980 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08006981 !audio_extn_usb_connected(NULL)) {
6982 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006983 ret = -ENOSYS;
6984 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006985 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006986 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006987 if (!in->standby && !in->is_st_session) {
6988 ALOGV("update input routing change");
6989 // inform adm before actual routing to prevent glitches.
6990 if (adev->adm_on_routing_change) {
6991 adev->adm_on_routing_change(adev->adm_data,
6992 in->capture_handle);
6993 ret = select_devices(adev, in->usecase);
6994 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6995 adev->adm_routing_changed = true;
6996 }
6997 }
6998 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006999 if (usb_addr)
7000 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007001 }
7002 pthread_mutex_unlock(&adev->lock);
7003 pthread_mutex_unlock(&in->lock);
7004
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007005 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007006 return ret;
7007}
7008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7010{
7011 struct stream_in *in = (struct stream_in *)stream;
7012 struct audio_device *adev = in->dev;
7013 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007014 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307015 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007016
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307017 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007018 parms = str_parms_create_str(kvpairs);
7019
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307020 if (!parms)
7021 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007022 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007023 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007024
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307025 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7026 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307027 strlcpy(in->profile, value, sizeof(in->profile));
7028 ALOGV("updating stream profile with value '%s'", in->profile);
7029 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7030 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007031 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307032 in->sample_rate, in->bit_width,
7033 in->profile, &in->app_type_cfg);
7034 }
7035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007036 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007037 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007038
7039 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307040error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307041 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007042}
7043
7044static char* in_get_parameters(const struct audio_stream *stream,
7045 const char *keys)
7046{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007047 struct stream_in *in = (struct stream_in *)stream;
7048 struct str_parms *query = str_parms_create_str(keys);
7049 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007050 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007051
7052 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007053 if (reply) {
7054 str_parms_destroy(reply);
7055 }
7056 if (query) {
7057 str_parms_destroy(query);
7058 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007059 ALOGE("in_get_parameters: failed to create query or reply");
7060 return NULL;
7061 }
7062
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007063 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007064
7065 voice_extn_in_get_parameters(in, query, reply);
7066
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007067 stream_get_parameter_channels(query, reply,
7068 &in->supported_channel_masks[0]);
7069 stream_get_parameter_formats(query, reply,
7070 &in->supported_formats[0]);
7071 stream_get_parameter_rates(query, reply,
7072 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007073 str = str_parms_to_str(reply);
7074 str_parms_destroy(query);
7075 str_parms_destroy(reply);
7076
7077 ALOGV("%s: exit: returns - %s", __func__, str);
7078 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007079}
7080
Aalique Grahame22e49102018-12-18 14:23:57 -08007081static int in_set_gain(struct audio_stream_in *stream,
7082 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007083{
Aalique Grahame22e49102018-12-18 14:23:57 -08007084 struct stream_in *in = (struct stream_in *)stream;
7085 char mixer_ctl_name[128];
7086 struct mixer_ctl *ctl;
7087 int ctl_value;
7088
7089 ALOGV("%s: gain %f", __func__, gain);
7090
7091 if (stream == NULL)
7092 return -EINVAL;
7093
7094 /* in_set_gain() only used to silence MMAP capture for now */
7095 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7096 return -ENOSYS;
7097
7098 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7099
7100 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7101 if (!ctl) {
7102 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7103 __func__, mixer_ctl_name);
7104 return -ENOSYS;
7105 }
7106
7107 if (gain < RECORD_GAIN_MIN)
7108 gain = RECORD_GAIN_MIN;
7109 else if (gain > RECORD_GAIN_MAX)
7110 gain = RECORD_GAIN_MAX;
7111 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7112
7113 mixer_ctl_set_value(ctl, 0, ctl_value);
7114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007115 return 0;
7116}
7117
7118static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7119 size_t bytes)
7120{
7121 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307122
7123 if (in == NULL) {
7124 ALOGE("%s: stream_in ptr is NULL", __func__);
7125 return -EINVAL;
7126 }
7127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007128 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307129 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307130 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007131
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007132 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307133
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007134 if (in->is_st_session) {
7135 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7136 /* Read from sound trigger HAL */
7137 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007138 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007139 if (adev->num_va_sessions < UINT_MAX)
7140 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007141 in->standby = 0;
7142 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007143 pthread_mutex_unlock(&in->lock);
7144 return bytes;
7145 }
7146
Haynes Mathew George16081042017-05-31 17:16:49 -07007147 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7148 ret = -ENOSYS;
7149 goto exit;
7150 }
7151
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007152 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7153 !in->standby && adev->adm_routing_changed) {
7154 ret = -ENOSYS;
7155 goto exit;
7156 }
7157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007158 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007159 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7160
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007161 pthread_mutex_lock(&adev->lock);
7162 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7163 ret = voice_extn_compress_voip_start_input_stream(in);
7164 else
7165 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007166 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7167 if (adev->num_va_sessions < UINT_MAX)
7168 adev->num_va_sessions++;
7169 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007170 pthread_mutex_unlock(&adev->lock);
7171 if (ret != 0) {
7172 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007173 }
7174 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007175
7176 // log startup time in ms.
7177 simple_stats_log(
7178 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007180
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307181 /* Avoid read if capture_stopped is set */
7182 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7183 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7184 ret = -EINVAL;
7185 goto exit;
7186 }
7187
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007188 // what's the duration requested by the client?
7189 long ns = 0;
7190
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307191 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007192 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7193 in->config.rate;
7194
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007195 ret = request_in_focus(in, ns);
7196 if (ret != 0)
7197 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007198 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007199
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307200 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307201 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7202 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307203 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007204 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307205 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007206 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007207 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007208 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007209 } else if (audio_extn_ffv_get_stream() == in) {
7210 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307211 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007212 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307213 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7214 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7215 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7216 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307217 ret = -EINVAL;
7218 goto exit;
7219 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307220 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307221 ret = -errno;
7222 }
7223 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307224 /* bytes read is always set to bytes for non compress usecases */
7225 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007226 }
7227
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007228 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007230 /*
Quinn Malef6050362019-01-30 15:55:40 -08007231 * Instead of writing zeroes here, we could trust the hardware to always
7232 * provide zeroes when muted. This is also muted with voice recognition
7233 * usecases so that other clients do not have access to voice recognition
7234 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007235 */
Quinn Malef6050362019-01-30 15:55:40 -08007236 if ((ret == 0 && voice_get_mic_mute(adev) &&
7237 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007238 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7239 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007240 (adev->num_va_sessions &&
7241 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7242 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7243 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 memset(buffer, 0, bytes);
7245
7246exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307247 frame_size = audio_stream_in_frame_size(stream);
7248 if (frame_size > 0)
7249 in->frames_read += bytes_read/frame_size;
7250
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007251 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307252 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007253 pthread_mutex_unlock(&in->lock);
7254
7255 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307256 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307257 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307258 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307259 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307260 in->standby = true;
7261 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307262 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307263 bytes_read = bytes;
7264 memset(buffer, 0, bytes);
7265 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007266 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007267 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7268 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007269 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307270 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307271 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007272 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307273 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007274}
7275
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007276static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007277{
7278 return 0;
7279}
7280
Aalique Grahame22e49102018-12-18 14:23:57 -08007281static int in_get_capture_position(const struct audio_stream_in *stream,
7282 int64_t *frames, int64_t *time)
7283{
7284 if (stream == NULL || frames == NULL || time == NULL) {
7285 return -EINVAL;
7286 }
7287 struct stream_in *in = (struct stream_in *)stream;
7288 int ret = -ENOSYS;
7289
7290 lock_input_stream(in);
7291 // note: ST sessions do not close the alsa pcm driver synchronously
7292 // on standby. Therefore, we may return an error even though the
7293 // pcm stream is still opened.
7294 if (in->standby) {
7295 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7296 "%s stream in standby but pcm not NULL for non ST session", __func__);
7297 goto exit;
7298 }
7299 if (in->pcm) {
7300 struct timespec timestamp;
7301 unsigned int avail;
7302 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7303 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007304 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007305 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007306 ret = 0;
7307 }
7308 }
7309exit:
7310 pthread_mutex_unlock(&in->lock);
7311 return ret;
7312}
7313
Carter Hsu2e429db2019-05-14 18:50:52 +08007314static int in_update_effect_list(bool add, effect_handle_t effect,
7315 struct listnode *head)
7316{
7317 struct listnode *node;
7318 struct in_effect_list *elist = NULL;
7319 struct in_effect_list *target = NULL;
7320 int ret = 0;
7321
7322 if (!head)
7323 return ret;
7324
7325 list_for_each(node, head) {
7326 elist = node_to_item(node, struct in_effect_list, list);
7327 if (elist->handle == effect) {
7328 target = elist;
7329 break;
7330 }
7331 }
7332
7333 if (add) {
7334 if (target) {
7335 ALOGD("effect %p already exist", effect);
7336 return ret;
7337 }
7338
7339 target = (struct in_effect_list *)
7340 calloc(1, sizeof(struct in_effect_list));
7341
7342 if (!target) {
7343 ALOGE("%s:fail to allocate memory", __func__);
7344 return -ENOMEM;
7345 }
7346
7347 target->handle = effect;
7348 list_add_tail(head, &target->list);
7349 } else {
7350 if (target) {
7351 list_remove(&target->list);
7352 free(target);
7353 }
7354 }
7355
7356 return ret;
7357}
7358
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007359static int add_remove_audio_effect(const struct audio_stream *stream,
7360 effect_handle_t effect,
7361 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007362{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007363 struct stream_in *in = (struct stream_in *)stream;
7364 int status = 0;
7365 effect_descriptor_t desc;
7366
7367 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007368 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7369
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007370 if (status != 0)
7371 return status;
7372
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007373 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007374 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007375 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007376 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7377 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007378 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007379
7380 in_update_effect_list(enable, effect, &in->aec_list);
7381 enable = !list_empty(&in->aec_list);
7382 if (enable == in->enable_aec)
7383 goto exit;
7384
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007385 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007386 ALOGD("AEC enable %d", enable);
7387
Aalique Grahame22e49102018-12-18 14:23:57 -08007388 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7389 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7390 in->dev->enable_voicerx = enable;
7391 struct audio_usecase *usecase;
7392 struct listnode *node;
7393 list_for_each(node, &in->dev->usecase_list) {
7394 usecase = node_to_item(node, struct audio_usecase, list);
7395 if (usecase->type == PCM_PLAYBACK)
7396 select_devices(in->dev, usecase->id);
7397 }
7398 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007399 if (!in->standby) {
7400 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7401 select_devices(in->dev, in->usecase);
7402 }
7403
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007404 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007405 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7406
7407 in_update_effect_list(enable, effect, &in->ns_list);
7408 enable = !list_empty(&in->ns_list);
7409 if (enable == in->enable_ns)
7410 goto exit;
7411
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007412 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007413 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007414 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007415 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7416 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007417 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7418 select_devices(in->dev, in->usecase);
7419 } else
7420 select_devices(in->dev, in->usecase);
7421 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007422 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007423exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007424 pthread_mutex_unlock(&in->dev->lock);
7425 pthread_mutex_unlock(&in->lock);
7426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007427 return 0;
7428}
7429
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007430static int in_add_audio_effect(const struct audio_stream *stream,
7431 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007432{
Eric Laurent994a6932013-07-17 11:51:42 -07007433 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007434 return add_remove_audio_effect(stream, effect, true);
7435}
7436
7437static int in_remove_audio_effect(const struct audio_stream *stream,
7438 effect_handle_t effect)
7439{
Eric Laurent994a6932013-07-17 11:51:42 -07007440 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007441 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007442}
7443
Haynes Mathew George16081042017-05-31 17:16:49 -07007444static int in_stop(const struct audio_stream_in* stream)
7445{
7446 struct stream_in *in = (struct stream_in *)stream;
7447 struct audio_device *adev = in->dev;
7448
7449 int ret = -ENOSYS;
7450 ALOGV("%s", __func__);
7451 pthread_mutex_lock(&adev->lock);
7452 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7453 in->capture_started && in->pcm != NULL) {
7454 pcm_stop(in->pcm);
7455 ret = stop_input_stream(in);
7456 in->capture_started = false;
7457 }
7458 pthread_mutex_unlock(&adev->lock);
7459 return ret;
7460}
7461
7462static int in_start(const struct audio_stream_in* stream)
7463{
7464 struct stream_in *in = (struct stream_in *)stream;
7465 struct audio_device *adev = in->dev;
7466 int ret = -ENOSYS;
7467
7468 ALOGV("%s in %p", __func__, in);
7469 pthread_mutex_lock(&adev->lock);
7470 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7471 !in->capture_started && in->pcm != NULL) {
7472 if (!in->capture_started) {
7473 ret = start_input_stream(in);
7474 if (ret == 0) {
7475 in->capture_started = true;
7476 }
7477 }
7478 }
7479 pthread_mutex_unlock(&adev->lock);
7480 return ret;
7481}
7482
Phil Burke0a86d12019-02-16 22:28:11 -08007483// Read offset for the positional timestamp from a persistent vendor property.
7484// This is to workaround apparent inaccuracies in the timing information that
7485// is used by the AAudio timing model. The inaccuracies can cause glitches.
7486static int64_t in_get_mmap_time_offset() {
7487 const int32_t kDefaultOffsetMicros = 0;
7488 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007489 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007490 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7491 return mmap_time_offset_micros * (int64_t)1000;
7492}
7493
Haynes Mathew George16081042017-05-31 17:16:49 -07007494static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7495 int32_t min_size_frames,
7496 struct audio_mmap_buffer_info *info)
7497{
7498 struct stream_in *in = (struct stream_in *)stream;
7499 struct audio_device *adev = in->dev;
7500 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007501 unsigned int offset1 = 0;
7502 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007503 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007504 uint32_t mmap_size = 0;
7505 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007506
7507 pthread_mutex_lock(&adev->lock);
7508 ALOGV("%s in %p", __func__, in);
7509
Sharad Sanglec6f32552018-05-04 16:15:38 +05307510 if (CARD_STATUS_OFFLINE == in->card_status||
7511 CARD_STATUS_OFFLINE == adev->card_status) {
7512 ALOGW("in->card_status or adev->card_status offline, try again");
7513 ret = -EIO;
7514 goto exit;
7515 }
7516
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307517 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007518 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7519 ret = -EINVAL;
7520 goto exit;
7521 }
7522 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7523 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7524 ALOGV("%s in %p", __func__, in);
7525 ret = -ENOSYS;
7526 goto exit;
7527 }
7528 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7529 if (in->pcm_device_id < 0) {
7530 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7531 __func__, in->pcm_device_id, in->usecase);
7532 ret = -EINVAL;
7533 goto exit;
7534 }
7535
7536 adjust_mmap_period_count(&in->config, min_size_frames);
7537
7538 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7539 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7540 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7541 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307542 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307543 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7544 in->card_status = CARD_STATUS_OFFLINE;
7545 adev->card_status = CARD_STATUS_OFFLINE;
7546 ret = -EIO;
7547 goto exit;
7548 }
7549
Haynes Mathew George16081042017-05-31 17:16:49 -07007550 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7551 step = "open";
7552 ret = -ENODEV;
7553 goto exit;
7554 }
7555
7556 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7557 if (ret < 0) {
7558 step = "begin";
7559 goto exit;
7560 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007561
juyuchen626833d2019-06-04 16:48:02 +08007562 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007563 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7564 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7565 info->burst_size_frames = in->config.period_size;
7566 ret = platform_get_mmap_data_fd(adev->platform,
7567 in->pcm_device_id, 1 /*capture*/,
7568 &info->shared_memory_fd,
7569 &mmap_size);
7570 if (ret < 0) {
7571 // Fall back to non exclusive mode
7572 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7573 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007574 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7575 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7576
Arun Mirpuri5d170872019-03-26 13:21:31 -07007577 if (mmap_size < buffer_size) {
7578 step = "mmap";
7579 goto exit;
7580 }
juyuchen626833d2019-06-04 16:48:02 +08007581 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007582 }
7583
7584 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007585
7586 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7587 if (ret < 0) {
7588 step = "commit";
7589 goto exit;
7590 }
7591
Phil Burke0a86d12019-02-16 22:28:11 -08007592 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7593
Haynes Mathew George16081042017-05-31 17:16:49 -07007594 in->standby = false;
7595 ret = 0;
7596
7597 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7598 __func__, info->shared_memory_address, info->buffer_size_frames);
7599
7600exit:
7601 if (ret != 0) {
7602 if (in->pcm == NULL) {
7603 ALOGE("%s: %s - %d", __func__, step, ret);
7604 } else {
7605 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7606 pcm_close(in->pcm);
7607 in->pcm = NULL;
7608 }
7609 }
7610 pthread_mutex_unlock(&adev->lock);
7611 return ret;
7612}
7613
7614static int in_get_mmap_position(const struct audio_stream_in *stream,
7615 struct audio_mmap_position *position)
7616{
7617 struct stream_in *in = (struct stream_in *)stream;
7618 ALOGVV("%s", __func__);
7619 if (position == NULL) {
7620 return -EINVAL;
7621 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307622 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007623 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307624 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007625 return -ENOSYS;
7626 }
7627 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307628 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007629 return -ENOSYS;
7630 }
7631 struct timespec ts = { 0, 0 };
7632 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7633 if (ret < 0) {
7634 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307635 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007636 return ret;
7637 }
Phil Burke0a86d12019-02-16 22:28:11 -08007638 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7639 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307640 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007641 return 0;
7642}
7643
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307644static int in_get_active_microphones(const struct audio_stream_in *stream,
7645 struct audio_microphone_characteristic_t *mic_array,
7646 size_t *mic_count) {
7647 struct stream_in *in = (struct stream_in *)stream;
7648 struct audio_device *adev = in->dev;
7649 ALOGVV("%s", __func__);
7650
7651 lock_input_stream(in);
7652 pthread_mutex_lock(&adev->lock);
7653 int ret = platform_get_active_microphones(adev->platform,
7654 audio_channel_count_from_in_mask(in->channel_mask),
7655 in->usecase, mic_array, mic_count);
7656 pthread_mutex_unlock(&adev->lock);
7657 pthread_mutex_unlock(&in->lock);
7658
7659 return ret;
7660}
7661
7662static int adev_get_microphones(const struct audio_hw_device *dev,
7663 struct audio_microphone_characteristic_t *mic_array,
7664 size_t *mic_count) {
7665 struct audio_device *adev = (struct audio_device *)dev;
7666 ALOGVV("%s", __func__);
7667
7668 pthread_mutex_lock(&adev->lock);
7669 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7670 pthread_mutex_unlock(&adev->lock);
7671
7672 return ret;
7673}
juyuchendb308c22019-01-21 11:57:17 -07007674
7675static void in_update_sink_metadata(struct audio_stream_in *stream,
7676 const struct sink_metadata *sink_metadata) {
7677
7678 if (stream == NULL
7679 || sink_metadata == NULL
7680 || sink_metadata->tracks == NULL) {
7681 return;
7682 }
7683
7684 int error = 0;
7685 struct stream_in *in = (struct stream_in *)stream;
7686 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007687 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007688 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007689
7690 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007691
7692 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007693 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007694
7695 lock_input_stream(in);
7696 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007697 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007698
Zhou Song62ea0282020-03-22 19:53:01 +08007699 is_ha_usecase = adev->ha_proxy_enable ?
7700 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7701 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7702 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007703 && adev->voice_tx_output != NULL) {
7704 /* Use the rx device from afe-proxy record to route voice call because
7705 there is no routing if tx device is on primary hal and rx device
7706 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007707 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007708
7709 if (!voice_is_call_state_active(adev)) {
7710 if (adev->mode == AUDIO_MODE_IN_CALL) {
7711 adev->current_call_output = adev->voice_tx_output;
7712 error = voice_start_call(adev);
7713 if (error != 0)
7714 ALOGE("%s: start voice call failed %d", __func__, error);
7715 }
7716 } else {
7717 adev->current_call_output = adev->voice_tx_output;
7718 voice_update_devices_for_all_voice_usecases(adev);
7719 }
7720 }
7721
7722 pthread_mutex_unlock(&adev->lock);
7723 pthread_mutex_unlock(&in->lock);
7724}
7725
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307726int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007727 audio_io_handle_t handle,
7728 audio_devices_t devices,
7729 audio_output_flags_t flags,
7730 struct audio_config *config,
7731 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007732 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007733{
7734 struct audio_device *adev = (struct audio_device *)dev;
7735 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307736 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007737 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007738 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307739 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007740 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7741 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7742 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7743 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007744 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007745 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7746 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007747 bool force_haptic_path =
7748 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007749 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007750#ifdef AUDIO_GKI_ENABLED
7751 __s32 *generic_dec;
7752#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007753
kunleizdff872d2018-08-20 14:40:33 +08007754 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007755 is_usb_dev = false;
7756 devices = AUDIO_DEVICE_OUT_SPEAKER;
7757 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7758 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007759 if (config->format == AUDIO_FORMAT_DEFAULT)
7760 config->format = AUDIO_FORMAT_PCM_16_BIT;
7761 if (config->sample_rate == 0)
7762 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7763 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7764 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007765 }
7766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007767 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007769 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7770
Mingming Yin3a941d42016-02-17 18:08:05 -08007771 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007772 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7773 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307774
7775
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007776 if (!out) {
7777 return -ENOMEM;
7778 }
7779
Haynes Mathew George204045b2015-02-25 20:32:03 -08007780 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007781 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007782 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007783 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007784 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007786 if (devices == AUDIO_DEVICE_NONE)
7787 devices = AUDIO_DEVICE_OUT_SPEAKER;
7788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007789 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007790 list_init(&out->device_list);
7791 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007792 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007793 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007794 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307795 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307796 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7797 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7798 else
7799 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007800 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007801 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007802 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307803 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307804 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007805 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007806 out->hal_output_suspend_supported = 0;
7807 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307808 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307809 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307810 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007811 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007812
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307813 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307814 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007815 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7816
Aalique Grahame22e49102018-12-18 14:23:57 -08007817 if (direct_dev &&
7818 (audio_is_linear_pcm(out->format) ||
7819 config->format == AUDIO_FORMAT_DEFAULT) &&
7820 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7821 audio_format_t req_format = config->format;
7822 audio_channel_mask_t req_channel_mask = config->channel_mask;
7823 uint32_t req_sample_rate = config->sample_rate;
7824
7825 pthread_mutex_lock(&adev->lock);
7826 if (is_hdmi) {
7827 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7828 ret = read_hdmi_sink_caps(out);
7829 if (config->sample_rate == 0)
7830 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7831 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7832 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7833 if (config->format == AUDIO_FORMAT_DEFAULT)
7834 config->format = AUDIO_FORMAT_PCM_16_BIT;
7835 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007836 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7837 &config->format,
7838 &out->supported_formats[0],
7839 MAX_SUPPORTED_FORMATS,
7840 &config->channel_mask,
7841 &out->supported_channel_masks[0],
7842 MAX_SUPPORTED_CHANNEL_MASKS,
7843 &config->sample_rate,
7844 &out->supported_sample_rates[0],
7845 MAX_SUPPORTED_SAMPLE_RATES);
7846 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007847 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007848
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007849 pthread_mutex_unlock(&adev->lock);
7850 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007851 if (ret == -ENOSYS) {
7852 /* ignore and go with default */
7853 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007854 }
7855 // For MMAP NO IRQ, allow conversions in ADSP
7856 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7857 goto error_open;
7858 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007859 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007860 goto error_open;
7861 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007862
7863 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7864 config->sample_rate = req_sample_rate;
7865 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7866 config->channel_mask = req_channel_mask;
7867 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7868 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007869 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007870
7871 out->sample_rate = config->sample_rate;
7872 out->channel_mask = config->channel_mask;
7873 out->format = config->format;
7874 if (is_hdmi) {
7875 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7876 out->config = pcm_config_hdmi_multi;
7877 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7878 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7879 out->config = pcm_config_mmap_playback;
7880 out->stream.start = out_start;
7881 out->stream.stop = out_stop;
7882 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7883 out->stream.get_mmap_position = out_get_mmap_position;
7884 } else {
7885 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7886 out->config = pcm_config_hifi;
7887 }
7888
7889 out->config.rate = out->sample_rate;
7890 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7891 if (is_hdmi) {
7892 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7893 audio_bytes_per_sample(out->format));
7894 }
7895 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007896 }
7897
Derek Chenf6318be2017-06-12 17:16:24 -04007898 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007899 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007900 /* extract car audio stream index */
7901 out->car_audio_stream =
7902 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7903 if (out->car_audio_stream < 0) {
7904 ALOGE("%s: invalid car audio stream %x",
7905 __func__, out->car_audio_stream);
7906 ret = -EINVAL;
7907 goto error_open;
7908 }
Derek Chen5f67a942020-02-24 23:08:13 -08007909 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007910 }
7911
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007912 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007913 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007914 if (!voice_extn_is_compress_voip_supported()) {
7915 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7916 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007917 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307918 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007919 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7920 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007921 out->volume_l = INVALID_OUT_VOLUME;
7922 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007923
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007924 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007925 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007926 uint32_t channel_count =
7927 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307928 out->config.channels = channel_count;
7929
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007930 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7931 out->sample_rate, out->format,
7932 channel_count, false);
7933 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7934 if (frame_size != 0)
7935 out->config.period_size = buffer_size / frame_size;
7936 else
7937 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007938 }
7939 } else {
7940 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7941 voice_extn_compress_voip_is_active(out->dev)) &&
7942 (voice_extn_compress_voip_is_config_supported(config))) {
7943 ret = voice_extn_compress_voip_open_output_stream(out);
7944 if (ret != 0) {
7945 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7946 __func__, ret);
7947 goto error_open;
7948 }
Sujin Panicker19027262019-09-16 18:28:06 +05307949 } else {
7950 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7951 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007952 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007953 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007954 } else if (audio_is_linear_pcm(out->format) &&
7955 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7956 out->channel_mask = config->channel_mask;
7957 out->sample_rate = config->sample_rate;
7958 out->format = config->format;
7959 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7960 // does this change?
7961 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7962 out->config.rate = config->sample_rate;
7963 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7964 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7965 audio_bytes_per_sample(config->format));
7966 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007967 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307968 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307969 pthread_mutex_lock(&adev->lock);
7970 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7971 pthread_mutex_unlock(&adev->lock);
7972
7973 // reject offload during card offline to allow
7974 // fallback to s/w paths
7975 if (offline) {
7976 ret = -ENODEV;
7977 goto error_open;
7978 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007980 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7981 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7982 ALOGE("%s: Unsupported Offload information", __func__);
7983 ret = -EINVAL;
7984 goto error_open;
7985 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007986
Atul Khare3fa6e542017-08-09 00:56:17 +05307987 if (config->offload_info.format == 0)
7988 config->offload_info.format = config->format;
7989 if (config->offload_info.sample_rate == 0)
7990 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007991
Mingming Yin90310102013-11-13 16:57:00 -08007992 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307993 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007994 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007995 ret = -EINVAL;
7996 goto error_open;
7997 }
7998
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007999 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8000 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8001 (audio_extn_passthru_is_passthrough_stream(out)) &&
8002 !((config->sample_rate == 48000) ||
8003 (config->sample_rate == 96000) ||
8004 (config->sample_rate == 192000))) {
8005 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8006 __func__, config->sample_rate, config->offload_info.format);
8007 ret = -EINVAL;
8008 goto error_open;
8009 }
8010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008011 out->compr_config.codec = (struct snd_codec *)
8012 calloc(1, sizeof(struct snd_codec));
8013
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008014 if (!out->compr_config.codec) {
8015 ret = -ENOMEM;
8016 goto error_open;
8017 }
8018
Dhananjay Kumarac341582017-02-23 23:42:25 +05308019 out->stream.pause = out_pause;
8020 out->stream.resume = out_resume;
8021 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308022 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308023 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008024 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308025 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008026 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308027 } else {
8028 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8029 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008030 }
vivek mehta446c3962015-09-14 10:57:35 -07008031
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308032 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8033 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008034#ifdef AUDIO_GKI_ENABLED
8035 /* out->compr_config.codec->reserved[1] is for flags */
8036 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8037#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308038 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008039#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308040 }
8041
vivek mehta446c3962015-09-14 10:57:35 -07008042 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008043 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008044 config->format == 0 && config->sample_rate == 0 &&
8045 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008046 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008047 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8048 } else {
8049 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8050 ret = -EEXIST;
8051 goto error_open;
8052 }
vivek mehta446c3962015-09-14 10:57:35 -07008053 }
8054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008055 if (config->offload_info.channel_mask)
8056 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008057 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008058 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008059 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008060 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308061 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008062 ret = -EINVAL;
8063 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008064 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008065
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008066 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008067 out->sample_rate = config->offload_info.sample_rate;
8068
Mingming Yin3ee55c62014-08-04 14:23:35 -07008069 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008070
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308071 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308072 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308073 audio_extn_dolby_send_ddp_endp_params(adev);
8074 audio_extn_dolby_set_dmid(adev);
8075 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008077 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008078 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008079 out->compr_config.codec->bit_rate =
8080 config->offload_info.bit_rate;
8081 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308082 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008083 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308084 /* Update bit width only for non passthrough usecases.
8085 * For passthrough usecases, the output will always be opened @16 bit
8086 */
8087 if (!audio_extn_passthru_is_passthrough_stream(out))
8088 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308089
8090 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008091#ifdef AUDIO_GKI_ENABLED
8092 /* out->compr_config.codec->reserved[1] is for flags */
8093 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8094 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8095#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308096 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8097 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008098#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308099
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008100 /*TODO: Do we need to change it for passthrough */
8101 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008102
Manish Dewangana6fc5442015-08-24 20:30:31 +05308103 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8104 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308105 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308106 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308107 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8108 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308109
8110 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8111 AUDIO_FORMAT_PCM) {
8112
8113 /*Based on platform support, configure appropriate alsa format for corresponding
8114 *hal input format.
8115 */
8116 out->compr_config.codec->format = hal_format_to_alsa(
8117 config->offload_info.format);
8118
Ashish Jain83a6cc22016-06-28 14:34:17 +05308119 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308120 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308121 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308122
Dhananjay Kumarac341582017-02-23 23:42:25 +05308123 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308124 *hal input format and alsa format might differ based on platform support.
8125 */
8126 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308127 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308128
8129 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8130
Deeraj Soman93155a62019-09-30 19:00:37 +05308131 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8132 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8133 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8134 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8135 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308136
Ashish Jainf1eaa582016-05-23 20:54:24 +05308137 /* Check if alsa session is configured with the same format as HAL input format,
8138 * if not then derive correct fragment size needed to accomodate the
8139 * conversion of HAL input format to alsa format.
8140 */
8141 audio_extn_utils_update_direct_pcm_fragment_size(out);
8142
8143 /*if hal input and output fragment size is different this indicates HAL input format is
8144 *not same as the alsa format
8145 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308146 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308147 /*Allocate a buffer to convert input data to the alsa configured format.
8148 *size of convert buffer is equal to the size required to hold one fragment size
8149 *worth of pcm data, this is because flinger does not write more than fragment_size
8150 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308151 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8152 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308153 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8154 ret = -ENOMEM;
8155 goto error_open;
8156 }
8157 }
8158 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8159 out->compr_config.fragment_size =
8160 audio_extn_passthru_get_buffer_size(&config->offload_info);
8161 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8162 } else {
8163 out->compr_config.fragment_size =
8164 platform_get_compress_offload_buffer_size(&config->offload_info);
8165 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8166 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008167
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308168 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8169 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8170 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008171 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8172#ifdef AUDIO_GKI_ENABLED
8173 generic_dec =
8174 &(out->compr_config.codec->options.generic.reserved[1]);
8175 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8176 AUDIO_OUTPUT_BIT_WIDTH;
8177#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308178 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008179#endif
8180 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008181
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308182 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8183 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8184 }
8185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008186 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8187 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008188
Manish Dewangan69426c82017-01-30 17:35:36 +05308189 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8190 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8191 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8192 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8193 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8194 } else {
8195 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8196 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008197
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308198 memset(&out->channel_map_param, 0,
8199 sizeof(struct audio_out_channel_map_param));
8200
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008201 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308202 out->send_next_track_params = false;
8203 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008204 out->offload_state = OFFLOAD_STATE_IDLE;
8205 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008206 out->writeAt.tv_sec = 0;
8207 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008208
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008209 audio_extn_dts_create_state_notifier_node(out->usecase);
8210
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008211 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8212 __func__, config->offload_info.version,
8213 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308214
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308215 /* Check if DSD audio format is supported in codec
8216 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308217 */
8218
8219 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308220 (!platform_check_codec_dsd_support(adev->platform) ||
8221 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308222 ret = -EINVAL;
8223 goto error_open;
8224 }
8225
Ashish Jain5106d362016-05-11 19:23:33 +05308226 /* Disable gapless if any of the following is true
8227 * passthrough playback
8228 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308229 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308230 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308231 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308232 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008233 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308234 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308235 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308236 check_and_set_gapless_mode(adev, false);
8237 } else
8238 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008239
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308240 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008241 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8242 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308243 if (config->format == AUDIO_FORMAT_DSD) {
8244 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008245#ifdef AUDIO_GKI_ENABLED
8246 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8247 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8248#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308249 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008250#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308251 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008252
8253 create_offload_callback_thread(out);
8254
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008255 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008256 switch (config->sample_rate) {
8257 case 0:
8258 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8259 break;
8260 case 8000:
8261 case 16000:
8262 case 48000:
8263 out->sample_rate = config->sample_rate;
8264 break;
8265 default:
8266 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8267 config->sample_rate);
8268 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8269 ret = -EINVAL;
8270 goto error_open;
8271 }
8272 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8273 switch (config->channel_mask) {
8274 case AUDIO_CHANNEL_NONE:
8275 case AUDIO_CHANNEL_OUT_STEREO:
8276 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8277 break;
8278 default:
8279 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8280 config->channel_mask);
8281 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8282 ret = -EINVAL;
8283 goto error_open;
8284 }
8285 switch (config->format) {
8286 case AUDIO_FORMAT_DEFAULT:
8287 case AUDIO_FORMAT_PCM_16_BIT:
8288 out->format = AUDIO_FORMAT_PCM_16_BIT;
8289 break;
8290 default:
8291 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8292 config->format);
8293 config->format = AUDIO_FORMAT_PCM_16_BIT;
8294 ret = -EINVAL;
8295 goto error_open;
8296 }
8297
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308298 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008299 if (ret != 0) {
8300 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008301 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008302 goto error_open;
8303 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008304 } else if (is_single_device_type_equal(&out->device_list,
8305 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008306 switch (config->sample_rate) {
8307 case 0:
8308 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8309 break;
8310 case 8000:
8311 case 16000:
8312 case 48000:
8313 out->sample_rate = config->sample_rate;
8314 break;
8315 default:
8316 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8317 config->sample_rate);
8318 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8319 ret = -EINVAL;
8320 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008321 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008322 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8323 switch (config->channel_mask) {
8324 case AUDIO_CHANNEL_NONE:
8325 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8326 break;
8327 case AUDIO_CHANNEL_OUT_STEREO:
8328 out->channel_mask = config->channel_mask;
8329 break;
8330 default:
8331 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8332 config->channel_mask);
8333 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8334 ret = -EINVAL;
8335 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008336 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008337 switch (config->format) {
8338 case AUDIO_FORMAT_DEFAULT:
8339 out->format = AUDIO_FORMAT_PCM_16_BIT;
8340 break;
8341 case AUDIO_FORMAT_PCM_16_BIT:
8342 out->format = config->format;
8343 break;
8344 default:
8345 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8346 config->format);
8347 config->format = AUDIO_FORMAT_PCM_16_BIT;
8348 ret = -EINVAL;
8349 break;
8350 }
8351 if (ret != 0)
8352 goto error_open;
8353
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008354 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8355 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008356 out->config.rate = out->sample_rate;
8357 out->config.channels =
8358 audio_channel_count_from_out_mask(out->channel_mask);
8359 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008360 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008361 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308362 unsigned int channels = 0;
8363 /*Update config params to default if not set by the caller*/
8364 if (config->sample_rate == 0)
8365 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8366 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8367 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8368 if (config->format == AUDIO_FORMAT_DEFAULT)
8369 config->format = AUDIO_FORMAT_PCM_16_BIT;
8370
8371 channels = audio_channel_count_from_out_mask(out->channel_mask);
8372
Varun Balaraje49253e2017-07-06 19:48:56 +05308373 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8374 out->usecase = get_interactive_usecase(adev);
8375 out->config = pcm_config_low_latency;
8376 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308377 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008378 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8379 out->flags);
8380 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008381 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8382 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8383 out->config = pcm_config_mmap_playback;
8384 out->stream.start = out_start;
8385 out->stream.stop = out_stop;
8386 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8387 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308388 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8389 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008390 out->hal_output_suspend_supported =
8391 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8392 out->dynamic_pm_qos_config_supported =
8393 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8394 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008395 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8396 } else {
8397 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8398 //the mixer path will be a string similar to "low-latency-playback resume"
8399 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8400 strlcat(out->pm_qos_mixer_path,
8401 " resume", MAX_MIXER_PATH_LEN);
8402 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8403 out->pm_qos_mixer_path);
8404 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308405 out->config = pcm_config_low_latency;
8406 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8407 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8408 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308409 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8410 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8411 if (out->config.period_size <= 0) {
8412 ALOGE("Invalid configuration period size is not valid");
8413 ret = -EINVAL;
8414 goto error_open;
8415 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008416 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8417 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8418 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008419 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8420 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8421 out->config = pcm_config_haptics_audio;
8422 if (force_haptic_path)
8423 adev->haptics_config = pcm_config_haptics_audio;
8424 else
8425 adev->haptics_config = pcm_config_haptics;
8426
Meng Wangd08ce322020-04-02 08:59:20 +08008427 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008428 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8429
8430 if (force_haptic_path) {
8431 out->config.channels = 1;
8432 adev->haptics_config.channels = 1;
8433 } else
8434 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 -08008435 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008436 ret = audio_extn_auto_hal_open_output_stream(out);
8437 if (ret) {
8438 ALOGE("%s: Failed to open output stream for bus device", __func__);
8439 ret = -EINVAL;
8440 goto error_open;
8441 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308442 } else {
8443 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008444 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8445 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308446 }
8447 out->hal_ip_format = format = out->format;
8448 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8449 out->hal_op_format = pcm_format_to_hal(out->config.format);
8450 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8451 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008452 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308453 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308454 if (out->hal_ip_format != out->hal_op_format) {
8455 uint32_t buffer_size = out->config.period_size *
8456 format_to_bitwidth_table[out->hal_op_format] *
8457 out->config.channels;
8458 out->convert_buffer = calloc(1, buffer_size);
8459 if (out->convert_buffer == NULL){
8460 ALOGE("Allocation failed for convert buffer for size %d",
8461 out->compr_config.fragment_size);
8462 ret = -ENOMEM;
8463 goto error_open;
8464 }
8465 ALOGD("Convert buffer allocated of size %d", buffer_size);
8466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467 }
8468
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008469 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8470 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308471
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008472 /* TODO remove this hardcoding and check why width is zero*/
8473 if (out->bit_width == 0)
8474 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308475 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008476 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008477 &out->device_list, out->flags,
8478 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308479 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308480 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008481 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008482 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8483 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008484 if(adev->primary_output == NULL)
8485 adev->primary_output = out;
8486 else {
8487 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008488 ret = -EEXIST;
8489 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008490 }
8491 }
8492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 /* Check if this usecase is already existing */
8494 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008495 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8496 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008497 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008499 ret = -EEXIST;
8500 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008501 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008503 pthread_mutex_unlock(&adev->lock);
8504
8505 out->stream.common.get_sample_rate = out_get_sample_rate;
8506 out->stream.common.set_sample_rate = out_set_sample_rate;
8507 out->stream.common.get_buffer_size = out_get_buffer_size;
8508 out->stream.common.get_channels = out_get_channels;
8509 out->stream.common.get_format = out_get_format;
8510 out->stream.common.set_format = out_set_format;
8511 out->stream.common.standby = out_standby;
8512 out->stream.common.dump = out_dump;
8513 out->stream.common.set_parameters = out_set_parameters;
8514 out->stream.common.get_parameters = out_get_parameters;
8515 out->stream.common.add_audio_effect = out_add_audio_effect;
8516 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8517 out->stream.get_latency = out_get_latency;
8518 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008519#ifdef NO_AUDIO_OUT
8520 out->stream.write = out_write_for_no_output;
8521#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008522 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008523#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008524 out->stream.get_render_position = out_get_render_position;
8525 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008526 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008527
Haynes Mathew George16081042017-05-31 17:16:49 -07008528 if (out->realtime)
8529 out->af_period_multiplier = af_period_multiplier;
8530 else
8531 out->af_period_multiplier = 1;
8532
Andy Hunga1f48fa2019-07-01 18:14:53 -07008533 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008535 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008536 out->volume_l = PLAYBACK_GAIN_MAX;
8537 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008538 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008539 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008540
8541 config->format = out->stream.common.get_format(&out->stream.common);
8542 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8543 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308544 register_format(out->format, out->supported_formats);
8545 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8546 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008547
Aalique Grahame22e49102018-12-18 14:23:57 -08008548 out->error_log = error_log_create(
8549 ERROR_LOG_ENTRIES,
8550 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8551
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308552 /*
8553 By locking output stream before registering, we allow the callback
8554 to update stream's state only after stream's initial state is set to
8555 adev state.
8556 */
8557 lock_output_stream(out);
8558 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8559 pthread_mutex_lock(&adev->lock);
8560 out->card_status = adev->card_status;
8561 pthread_mutex_unlock(&adev->lock);
8562 pthread_mutex_unlock(&out->lock);
8563
Aalique Grahame22e49102018-12-18 14:23:57 -08008564 stream_app_type_cfg_init(&out->app_type_cfg);
8565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008566 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308567 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008568 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008569
8570 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8571 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8572 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008573 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308574 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008575 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008576 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308577 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8578 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008579 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8580 out->usecase, PCM_PLAYBACK);
8581 hdlr_stream_cfg.flags = out->flags;
8582 hdlr_stream_cfg.type = PCM_PLAYBACK;
8583 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8584 &hdlr_stream_cfg);
8585 if (ret) {
8586 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8587 out->adsp_hdlr_stream_handle = NULL;
8588 }
8589 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308590 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8591 is_direct_passthough, false);
8592 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8593 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008594 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008595 if (ret < 0) {
8596 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8597 out->ip_hdlr_handle = NULL;
8598 }
8599 }
Derek Chenf939fb72018-11-13 13:34:41 -08008600
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008601 ret = io_streams_map_insert(adev, &out->stream.common,
8602 out->handle, AUDIO_PATCH_HANDLE_NONE);
8603 if (ret != 0)
8604 goto error_open;
8605
Susan Wang6dd13092021-01-25 10:27:11 -05008606 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008607
8608 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008609 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008610 pthread_mutex_unlock(&adev->lock);
8611
Eric Laurent994a6932013-07-17 11:51:42 -07008612 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008613 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008614
8615error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308616 if (out->convert_buffer)
8617 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008618 free(out);
8619 *stream_out = NULL;
8620 ALOGD("%s: exit: ret %d", __func__, ret);
8621 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008622}
8623
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308624void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008625 struct audio_stream_out *stream)
8626{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008627 struct stream_out *out = (struct stream_out *)stream;
8628 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008629 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008630
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008631 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308632
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008633 io_streams_map_remove(adev, out->handle);
8634
Susan Wang6dd13092021-01-25 10:27:11 -05008635 // remove out_ctxt early to prevent the stream
8636 // being opened in a race condition
8637 pthread_mutex_lock(&adev->lock);
8638 list_remove(&out->out_ctxt.list);
8639 pthread_mutex_unlock(&adev->lock);
8640
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308641 // must deregister from sndmonitor first to prevent races
8642 // between the callback and close_stream
8643 audio_extn_snd_mon_unregister_listener(out);
8644
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008645 /* close adsp hdrl session before standby */
8646 if (out->adsp_hdlr_stream_handle) {
8647 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8648 if (ret)
8649 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8650 out->adsp_hdlr_stream_handle = NULL;
8651 }
8652
Manish Dewangan21a850a2017-08-14 12:03:55 +05308653 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008654 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8655 out->ip_hdlr_handle = NULL;
8656 }
8657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008658 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308659 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008660 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308661 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308662 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008663 if(ret != 0)
8664 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8665 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008666 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008667 out_standby(&stream->common);
8668
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008669 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008670 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008671 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008672 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008673 if (out->compr_config.codec != NULL)
8674 free(out->compr_config.codec);
8675 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008676
Zhou Songbaddf9f2020-11-20 13:57:39 +08008677 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308678
Varun Balaraje49253e2017-07-06 19:48:56 +05308679 if (is_interactive_usecase(out->usecase))
8680 free_interactive_usecase(adev, out->usecase);
8681
Ashish Jain83a6cc22016-06-28 14:34:17 +05308682 if (out->convert_buffer != NULL) {
8683 free(out->convert_buffer);
8684 out->convert_buffer = NULL;
8685 }
8686
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008687 if (adev->voice_tx_output == out)
8688 adev->voice_tx_output = NULL;
8689
Aalique Grahame22e49102018-12-18 14:23:57 -08008690 error_log_destroy(out->error_log);
8691 out->error_log = NULL;
8692
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308693 if (adev->primary_output == out)
8694 adev->primary_output = NULL;
8695
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008696 pthread_cond_destroy(&out->cond);
8697 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008698 pthread_mutex_destroy(&out->pre_lock);
8699 pthread_mutex_destroy(&out->latch_lock);
8700 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008701
8702 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008703 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008704 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008705 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008706}
8707
8708static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8709{
8710 struct audio_device *adev = (struct audio_device *)dev;
8711 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008712 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008713 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008714 int ret;
8715 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008716 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008717 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008718 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008719
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008720 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008721 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008722
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308723 if (!parms)
8724 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308725
Derek Chen6f293672019-04-01 01:40:24 -07008726 /* notify adev and input/output streams on the snd card status */
8727 adev_snd_mon_cb((void *)adev, parms);
8728
Weiyin Jiang24f55292020-12-22 14:35:46 +08008729 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8730 if (ret >= 0) {
8731 list_for_each(node, &adev->active_outputs_list) {
8732 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8733 streams_output_ctxt_t,
8734 list);
8735 out_snd_mon_cb((void *)out_ctxt->output, parms);
8736 }
Derek Chen6f293672019-04-01 01:40:24 -07008737
Weiyin Jiang24f55292020-12-22 14:35:46 +08008738 list_for_each(node, &adev->active_inputs_list) {
8739 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8740 streams_input_ctxt_t,
8741 list);
8742 in_snd_mon_cb((void *)in_ctxt->input, parms);
8743 }
Derek Chen6f293672019-04-01 01:40:24 -07008744 }
8745
Zhou Songd6d71752019-05-21 18:08:51 +08008746 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308747 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8748 if (ret >= 0) {
8749 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008750 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308751 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308752 /*
8753 * When ever BT_SCO=ON arrives, make sure to route
8754 * all use cases to SCO device, otherwise due to delay in
8755 * BT_SCO=ON and lack of synchronization with create audio patch
8756 * request for SCO device, some times use case not routed properly to
8757 * SCO device
8758 */
8759 struct audio_usecase *usecase;
8760 struct listnode *node;
8761 list_for_each(node, &adev->usecase_list) {
8762 usecase = node_to_item(node, struct audio_usecase, list);
8763 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
8764 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device))) {
8765 ALOGD("BT_SCO ON, switch all in use case to it");
8766 select_devices(adev, usecase->id);
8767 }
8768 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
8769 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE))) {
8770 ALOGD("BT_SCO ON, switch all out use case to it");
8771 select_devices(adev, usecase->id);
8772 }
8773 }
8774 }
8775 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308776 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008777 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008778 }
8779 }
8780
8781 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008782 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008783 if (!strncmp(value, "false", 5) &&
8784 audio_extn_a2dp_source_is_suspended()) {
8785 struct audio_usecase *usecase;
8786 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008787 list_for_each(node, &adev->usecase_list) {
8788 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008789 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008790 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008791 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008792 reassign_device_list(&usecase->stream.in->device_list,
8793 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008794 select_devices(adev, usecase->id);
8795 }
Zhou Songd6d71752019-05-21 18:08:51 +08008796 }
8797 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308798 }
8799
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008800 status = voice_set_parameters(adev, parms);
8801 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008802 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008803
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008804 status = platform_set_parameters(adev->platform, parms);
8805 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008806 goto done;
8807
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008808 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8809 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008810 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008811 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8812 adev->bluetooth_nrec = true;
8813 else
8814 adev->bluetooth_nrec = false;
8815 }
8816
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008817 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8818 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008819 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8820 adev->screen_off = false;
8821 else
8822 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008823 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824 }
8825
Eric Laurent4b084132018-10-19 17:33:43 -07008826 ret = str_parms_get_int(parms, "rotation", &val);
8827 if (ret >= 0) {
8828 bool reverse_speakers = false;
8829 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8830 switch (val) {
8831 // FIXME: note that the code below assumes that the speakers are in the correct placement
8832 // relative to the user when the device is rotated 90deg from its default rotation. This
8833 // assumption is device-specific, not platform-specific like this code.
8834 case 270:
8835 reverse_speakers = true;
8836 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8837 break;
8838 case 0:
8839 case 180:
8840 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8841 break;
8842 case 90:
8843 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8844 break;
8845 default:
8846 ALOGE("%s: unexpected rotation of %d", __func__, val);
8847 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008848 }
Eric Laurent4b084132018-10-19 17:33:43 -07008849 if (status == 0) {
8850 // check and set swap
8851 // - check if orientation changed and speaker active
8852 // - set rotation and cache the rotation value
8853 adev->camera_orientation =
8854 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8855 if (!audio_extn_is_maxx_audio_enabled())
8856 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8857 }
8858 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008859
Mingming Yin514a8bc2014-07-29 15:22:21 -07008860 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8861 if (ret >= 0) {
8862 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8863 adev->bt_wb_speech_enabled = true;
8864 else
8865 adev->bt_wb_speech_enabled = false;
8866 }
8867
Zhou Song12c29502019-03-16 10:37:18 +08008868 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8869 if (ret >= 0) {
8870 val = atoi(value);
8871 adev->swb_speech_mode = val;
8872 }
8873
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008874 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8875 if (ret >= 0) {
8876 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308877 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008878 if (audio_is_output_device(val) &&
8879 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008880 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008881 platform_get_controller_stream_from_params(parms, &controller, &stream);
8882 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8883 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008884 if (ret < 0) {
8885 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308886 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008887 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008888 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308889 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008890 /*
8891 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8892 * Per AudioPolicyManager, USB device is higher priority than WFD.
8893 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8894 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8895 * starting voice call on USB
8896 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008897 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308898 if (ret >= 0)
8899 audio_extn_usb_add_device(device, atoi(value));
8900
Zhou Song6f862822017-11-06 17:27:57 +08008901 if (!audio_extn_usb_is_tunnel_supported()) {
8902 ALOGV("detected USB connect .. disable proxy");
8903 adev->allow_afe_proxy_usage = false;
8904 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008905 }
8906 }
8907
8908 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8909 if (ret >= 0) {
8910 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308911 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008912 /*
8913 * The HDMI / Displayport disconnect handling has been moved to
8914 * audio extension to ensure that its parameters are not
8915 * invalidated prior to updating sysfs of the disconnect event
8916 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8917 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308918 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008919 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308920 if (ret >= 0)
8921 audio_extn_usb_remove_device(device, atoi(value));
8922
Zhou Song6f862822017-11-06 17:27:57 +08008923 if (!audio_extn_usb_is_tunnel_supported()) {
8924 ALOGV("detected USB disconnect .. enable proxy");
8925 adev->allow_afe_proxy_usage = true;
8926 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008927 }
8928 }
8929
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008930 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008931
8932 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008933 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308934 struct audio_usecase *usecase;
8935 struct listnode *node;
8936 list_for_each(node, &adev->usecase_list) {
8937 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008938 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8939 continue;
8940
8941 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308942 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308943 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308944 ALOGD("Switching to speaker and muting the stream before select_devices");
8945 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308946 //force device switch to re configure encoder
8947 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308948 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08008949 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308950 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308951 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008952 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008953 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08008954 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008955 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8956 reassign_device_list(&usecase->stream.out->device_list,
8957 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8958 check_a2dp_restore_l(adev, usecase->stream.out, true);
8959 break;
8960 }
8961 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308962 }
8963 }
8964 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008965
8966 //handle vr audio setparam
8967 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8968 value, sizeof(value));
8969 if (ret >= 0) {
8970 ALOGI("Setting vr mode to be %s", value);
8971 if (!strncmp(value, "true", 4)) {
8972 adev->vr_audio_mode_enabled = true;
8973 ALOGI("Setting vr mode to true");
8974 } else if (!strncmp(value, "false", 5)) {
8975 adev->vr_audio_mode_enabled = false;
8976 ALOGI("Setting vr mode to false");
8977 } else {
8978 ALOGI("wrong vr mode set");
8979 }
8980 }
8981
Eric Laurent4b084132018-10-19 17:33:43 -07008982 //FIXME: to be replaced by proper video capture properties API
8983 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8984 if (ret >= 0) {
8985 int camera_facing = CAMERA_FACING_BACK;
8986 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8987 camera_facing = CAMERA_FACING_FRONT;
8988 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8989 camera_facing = CAMERA_FACING_BACK;
8990 else {
8991 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8992 goto done;
8993 }
8994 adev->camera_orientation =
8995 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8996 struct audio_usecase *usecase;
8997 struct listnode *node;
8998 list_for_each(node, &adev->usecase_list) {
8999 usecase = node_to_item(node, struct audio_usecase, list);
9000 struct stream_in *in = usecase->stream.in;
9001 if (usecase->type == PCM_CAPTURE && in != NULL &&
9002 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9003 select_devices(adev, in->usecase);
9004 }
9005 }
9006 }
9007
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309008 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009009done:
9010 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009011 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309012error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009013 ALOGV("%s: exit with code(%d)", __func__, status);
9014 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009015}
9016
9017static char* adev_get_parameters(const struct audio_hw_device *dev,
9018 const char *keys)
9019{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309020 ALOGD("%s:%s", __func__, keys);
9021
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009022 struct audio_device *adev = (struct audio_device *)dev;
9023 struct str_parms *reply = str_parms_create();
9024 struct str_parms *query = str_parms_create_str(keys);
9025 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309026 char value[256] = {0};
9027 int ret = 0;
9028
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009029 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009030 if (reply) {
9031 str_parms_destroy(reply);
9032 }
9033 if (query) {
9034 str_parms_destroy(query);
9035 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009036 ALOGE("adev_get_parameters: failed to create query or reply");
9037 return NULL;
9038 }
9039
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009040 //handle vr audio getparam
9041
9042 ret = str_parms_get_str(query,
9043 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9044 value, sizeof(value));
9045
9046 if (ret >= 0) {
9047 bool vr_audio_enabled = false;
9048 pthread_mutex_lock(&adev->lock);
9049 vr_audio_enabled = adev->vr_audio_mode_enabled;
9050 pthread_mutex_unlock(&adev->lock);
9051
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009052 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009053
9054 if (vr_audio_enabled) {
9055 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9056 "true");
9057 goto exit;
9058 } else {
9059 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9060 "false");
9061 goto exit;
9062 }
9063 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009064
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009065 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009066 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009067 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009068 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009069 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009070 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309071 pthread_mutex_unlock(&adev->lock);
9072
Naresh Tannirud7205b62014-06-20 02:54:48 +05309073exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009074 str = str_parms_to_str(reply);
9075 str_parms_destroy(query);
9076 str_parms_destroy(reply);
9077
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009078 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009079 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009080}
9081
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009082static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009083{
9084 return 0;
9085}
9086
9087static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9088{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009089 int ret;
9090 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009091
9092 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9093
Haynes Mathew George5191a852013-09-11 14:19:36 -07009094 pthread_mutex_lock(&adev->lock);
9095 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009096 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009097 pthread_mutex_unlock(&adev->lock);
9098 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009099}
9100
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009101static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9102 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009103{
9104 return -ENOSYS;
9105}
9106
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009107static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9108 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009109{
9110 return -ENOSYS;
9111}
9112
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009113static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9114 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009115{
9116 return -ENOSYS;
9117}
9118
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009119static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9120 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121{
9122 return -ENOSYS;
9123}
9124
9125static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9126{
9127 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009128 struct listnode *node;
9129 struct audio_usecase *usecase = NULL;
9130 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009132 pthread_mutex_lock(&adev->lock);
9133 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309134 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9135 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009136 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009137 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309138 adev->current_call_output = adev->primary_output;
9139 voice_start_call(adev);
9140 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009141 (mode == AUDIO_MODE_NORMAL ||
9142 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009143 list_for_each(node, &adev->usecase_list) {
9144 usecase = node_to_item(node, struct audio_usecase, list);
9145 if (usecase->type == VOICE_CALL)
9146 break;
9147 }
9148 if (usecase &&
9149 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9150 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9151 true);
9152 if (ret != 0) {
9153 /* default service interval was successfully updated,
9154 reopen USB backend with new service interval */
9155 check_usecases_codec_backend(adev,
9156 usecase,
9157 usecase->out_snd_device);
9158 }
9159 }
9160
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009161 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009162 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009163 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009164 // restore device for other active usecases after stop call
9165 list_for_each(node, &adev->usecase_list) {
9166 usecase = node_to_item(node, struct audio_usecase, list);
9167 select_devices(adev, usecase->id);
9168 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009170 }
9171 pthread_mutex_unlock(&adev->lock);
9172 return 0;
9173}
9174
9175static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9176{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009177 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009178 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009179
9180 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009181 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009182 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009183
Derek Chend2530072014-11-24 12:39:14 -08009184 if (adev->ext_hw_plugin)
9185 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009186
9187 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009188 pthread_mutex_unlock(&adev->lock);
9189
9190 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009191}
9192
9193static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9194{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009195 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009196 return 0;
9197}
9198
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009199static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009200 const struct audio_config *config)
9201{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009202 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009203
Aalique Grahame22e49102018-12-18 14:23:57 -08009204 /* Don't know if USB HIFI in this context so use true to be conservative */
9205 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9206 true /*is_usb_hifi */) != 0)
9207 return 0;
9208
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009209 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9210 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009211}
9212
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009213static bool adev_input_allow_hifi_record(struct audio_device *adev,
9214 audio_devices_t devices,
9215 audio_input_flags_t flags,
9216 audio_source_t source) {
9217 const bool allowed = true;
9218
9219 if (!audio_is_usb_in_device(devices))
9220 return !allowed;
9221
9222 switch (flags) {
9223 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009224 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009225 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9226 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009227 default:
9228 return !allowed;
9229 }
9230
9231 switch (source) {
9232 case AUDIO_SOURCE_DEFAULT:
9233 case AUDIO_SOURCE_MIC:
9234 case AUDIO_SOURCE_UNPROCESSED:
9235 break;
9236 default:
9237 return !allowed;
9238 }
9239
9240 switch (adev->mode) {
9241 case 0:
9242 break;
9243 default:
9244 return !allowed;
9245 }
9246
9247 return allowed;
9248}
9249
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009250static int adev_update_voice_comm_input_stream(struct stream_in *in,
9251 struct audio_config *config)
9252{
9253 bool valid_rate = (config->sample_rate == 8000 ||
9254 config->sample_rate == 16000 ||
9255 config->sample_rate == 32000 ||
9256 config->sample_rate == 48000);
9257 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9258
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009259 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009260 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009261 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9262 in->config = default_pcm_config_voip_copp;
9263 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9264 DEFAULT_VOIP_BUF_DURATION_MS,
9265 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009266 } else {
9267 ALOGW("%s No valid input in voip, use defaults"
9268 "sample rate %u, channel mask 0x%X",
9269 __func__, config->sample_rate, in->channel_mask);
9270 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009271 in->config.rate = config->sample_rate;
9272 in->sample_rate = config->sample_rate;
9273 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009274 //XXX needed for voice_extn_compress_voip_open_input_stream
9275 in->config.rate = config->sample_rate;
9276 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309277 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009278 voice_extn_compress_voip_is_active(in->dev)) &&
9279 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9280 valid_rate && valid_ch) {
9281 voice_extn_compress_voip_open_input_stream(in);
9282 // update rate entries to match config from AF
9283 in->config.rate = config->sample_rate;
9284 in->sample_rate = config->sample_rate;
9285 } else {
9286 ALOGW("%s compress voip not active, use defaults", __func__);
9287 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009288 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009289 return 0;
9290}
9291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009292static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009293 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009294 audio_devices_t devices,
9295 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009296 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309297 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009298 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009299 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009300{
9301 struct audio_device *adev = (struct audio_device *)dev;
9302 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009303 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009304 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009305 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309306 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009307 bool is_usb_dev = audio_is_usb_in_device(devices);
9308 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9309 devices,
9310 flags,
9311 source);
Andy Hung94320602018-10-29 18:31:12 -07009312 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9313 " sample_rate %u, channel_mask %#x, format %#x",
9314 __func__, flags, is_usb_dev, may_use_hifi_record,
9315 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309316
kunleizdff872d2018-08-20 14:40:33 +08009317 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009318 is_usb_dev = false;
9319 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9320 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9321 __func__, devices);
9322 }
9323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009324 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009325
9326 if (!(is_usb_dev && may_use_hifi_record)) {
9327 if (config->sample_rate == 0)
9328 config->sample_rate = 48000;
9329 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9330 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9331 if (config->format == AUDIO_FORMAT_DEFAULT)
9332 config->format = AUDIO_FORMAT_PCM_16_BIT;
9333
9334 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9335
Aalique Grahame22e49102018-12-18 14:23:57 -08009336 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9337 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009338 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309339 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009340
9341 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009342
9343 if (!in) {
9344 ALOGE("failed to allocate input stream");
9345 return -ENOMEM;
9346 }
9347
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309348 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309349 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9350 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009351 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009352 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009354 in->stream.common.get_sample_rate = in_get_sample_rate;
9355 in->stream.common.set_sample_rate = in_set_sample_rate;
9356 in->stream.common.get_buffer_size = in_get_buffer_size;
9357 in->stream.common.get_channels = in_get_channels;
9358 in->stream.common.get_format = in_get_format;
9359 in->stream.common.set_format = in_set_format;
9360 in->stream.common.standby = in_standby;
9361 in->stream.common.dump = in_dump;
9362 in->stream.common.set_parameters = in_set_parameters;
9363 in->stream.common.get_parameters = in_get_parameters;
9364 in->stream.common.add_audio_effect = in_add_audio_effect;
9365 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9366 in->stream.set_gain = in_set_gain;
9367 in->stream.read = in_read;
9368 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009369 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309370 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009371 in->stream.set_microphone_direction = in_set_microphone_direction;
9372 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009373 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009374
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009375 list_init(&in->device_list);
9376 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009377 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009378 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009379 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009380 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009381 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009382 in->bit_width = 16;
9383 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009384 in->direction = MIC_DIRECTION_UNSPECIFIED;
9385 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009386 list_init(&in->aec_list);
9387 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009388 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009389
Andy Hung94320602018-10-29 18:31:12 -07009390 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009391 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9392 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9393 /* Force channel config requested to mono if incall
9394 record is being requested for only uplink/downlink */
9395 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9396 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9397 ret = -EINVAL;
9398 goto err_open;
9399 }
9400 }
9401
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009402 if (is_usb_dev && may_use_hifi_record) {
9403 /* HiFi record selects an appropriate format, channel, rate combo
9404 depending on sink capabilities*/
9405 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9406 &config->format,
9407 &in->supported_formats[0],
9408 MAX_SUPPORTED_FORMATS,
9409 &config->channel_mask,
9410 &in->supported_channel_masks[0],
9411 MAX_SUPPORTED_CHANNEL_MASKS,
9412 &config->sample_rate,
9413 &in->supported_sample_rates[0],
9414 MAX_SUPPORTED_SAMPLE_RATES);
9415 if (ret != 0) {
9416 ret = -EINVAL;
9417 goto err_open;
9418 }
9419 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009420 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309421 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309422 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9423 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9424 in->config.format = PCM_FORMAT_S32_LE;
9425 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309426 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9427 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9428 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9429 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9430 bool ret_error = false;
9431 in->bit_width = 24;
9432 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9433 from HAL is 24_packed and 8_24
9434 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9435 24_packed return error indicating supported format is 24_packed
9436 *> In case of any other source requesting 24 bit or float return error
9437 indicating format supported is 16 bit only.
9438
9439 on error flinger will retry with supported format passed
9440 */
9441 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9442 (source != AUDIO_SOURCE_CAMCORDER)) {
9443 config->format = AUDIO_FORMAT_PCM_16_BIT;
9444 if (config->sample_rate > 48000)
9445 config->sample_rate = 48000;
9446 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009447 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9448 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309449 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9450 ret_error = true;
9451 }
9452
9453 if (ret_error) {
9454 ret = -EINVAL;
9455 goto err_open;
9456 }
9457 }
9458
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009459 in->channel_mask = config->channel_mask;
9460 in->format = config->format;
9461
9462 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309463
Huicheng Liu1404ba12020-09-11 01:03:25 -04009464 /* validate bus device address */
9465 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9466 /* extract car audio stream index */
9467 in->car_audio_stream =
9468 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9469 if (in->car_audio_stream < 0) {
9470 ALOGE("%s: invalid car audio stream %x",
9471 __func__, in->car_audio_stream);
9472 ret = -EINVAL;
9473 goto err_open;
9474 }
9475 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009476 ret = audio_extn_auto_hal_open_input_stream(in);
9477 if (ret) {
9478 ALOGE("%s: Failed to open input stream for bus device", __func__);
9479 ret = -EINVAL;
9480 goto err_open;
9481 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009482 }
9483
Susan Wange3959562021-03-11 11:50:26 -05009484 /* reassign use case for echo reference stream on automotive platforms */
9485 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9486 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9487 }
9488
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309489 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9490 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9491 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9492 else {
9493 ret = -EINVAL;
9494 goto err_open;
9495 }
9496 }
9497
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009498 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309499 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9500 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009501 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9502 is_low_latency = true;
9503#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309504 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9505 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9506 else
9507 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009508#endif
9509 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009510 if (!in->realtime) {
9511 in->config = pcm_config_audio_capture;
9512 frame_size = audio_stream_in_frame_size(&in->stream);
9513 buffer_size = get_input_buffer_size(config->sample_rate,
9514 config->format,
9515 channel_count,
9516 is_low_latency);
9517 in->config.period_size = buffer_size / frame_size;
9518 in->config.rate = config->sample_rate;
9519 in->af_period_multiplier = 1;
9520 } else {
9521 // period size is left untouched for rt mode playback
9522 in->config = pcm_config_audio_capture_rt;
9523 in->af_period_multiplier = af_period_multiplier;
9524 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009525 }
9526
9527 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9528 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9529 in->realtime = 0;
9530 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9531 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009532 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009533 in->stream.start = in_start;
9534 in->stream.stop = in_stop;
9535 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9536 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009537 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009538 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009539 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9540 in->config = pcm_config_audio_capture;
9541 frame_size = audio_stream_in_frame_size(&in->stream);
9542 buffer_size = get_input_buffer_size(config->sample_rate,
9543 config->format,
9544 channel_count,
9545 false /*is_low_latency*/);
9546 in->config.period_size = buffer_size / frame_size;
9547 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009548 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009549 switch (config->format) {
9550 case AUDIO_FORMAT_PCM_32_BIT:
9551 in->bit_width = 32;
9552 break;
9553 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9554 case AUDIO_FORMAT_PCM_8_24_BIT:
9555 in->bit_width = 24;
9556 break;
9557 default:
9558 in->bit_width = 16;
9559 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009560 } else if (is_single_device_type_equal(&in->device_list,
9561 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9562 is_single_device_type_equal(&in->device_list,
9563 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009564 if (config->sample_rate == 0)
9565 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9566 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9567 config->sample_rate != 8000) {
9568 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9569 ret = -EINVAL;
9570 goto err_open;
9571 }
9572 if (config->format == AUDIO_FORMAT_DEFAULT)
9573 config->format = AUDIO_FORMAT_PCM_16_BIT;
9574 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9575 config->format = AUDIO_FORMAT_PCM_16_BIT;
9576 ret = -EINVAL;
9577 goto err_open;
9578 }
9579
9580 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009581 if (adev->ha_proxy_enable &&
9582 is_single_device_type_equal(&in->device_list,
9583 AUDIO_DEVICE_IN_TELEPHONY_RX))
9584 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009585 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009586 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009587 in->af_period_multiplier = 1;
9588 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309589 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009590 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9591 (config->sample_rate == 8000 ||
9592 config->sample_rate == 16000 ||
9593 config->sample_rate == 32000 ||
9594 config->sample_rate == 48000) &&
9595 channel_count == 1) {
9596 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9597 in->config = pcm_config_audio_capture;
9598 frame_size = audio_stream_in_frame_size(&in->stream);
9599 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9600 config->sample_rate,
9601 config->format,
9602 channel_count, false /*is_low_latency*/);
9603 in->config.period_size = buffer_size / frame_size;
9604 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9605 in->config.rate = config->sample_rate;
9606 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009607 } else if (in->realtime) {
9608 in->config = pcm_config_audio_capture_rt;
9609 in->config.format = pcm_format_from_audio_format(config->format);
9610 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009611 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309612 int ret_val;
9613 pthread_mutex_lock(&adev->lock);
9614 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9615 in, config, &channel_mask_updated);
9616 pthread_mutex_unlock(&adev->lock);
9617
9618 if (!ret_val) {
9619 if (channel_mask_updated == true) {
9620 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9621 __func__, config->channel_mask);
9622 ret = -EINVAL;
9623 goto err_open;
9624 }
9625 ALOGD("%s: created multi-channel session succesfully",__func__);
9626 } else if (audio_extn_compr_cap_enabled() &&
9627 audio_extn_compr_cap_format_supported(config->format) &&
9628 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9629 audio_extn_compr_cap_init(in);
9630 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309631 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309632 if (ret)
9633 goto err_open;
9634 } else {
9635 in->config = pcm_config_audio_capture;
9636 in->config.rate = config->sample_rate;
9637 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309638 in->format = config->format;
9639 frame_size = audio_stream_in_frame_size(&in->stream);
9640 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009641 config->format,
9642 channel_count,
9643 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009644 /* prevent division-by-zero */
9645 if (frame_size == 0) {
9646 ALOGE("%s: Error frame_size==0", __func__);
9647 ret = -EINVAL;
9648 goto err_open;
9649 }
9650
Revathi Uddarajud2634032017-12-07 14:42:34 +05309651 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009652 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009653
Revathi Uddarajud2634032017-12-07 14:42:34 +05309654 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9655 /* optionally use VOIP usecase depending on config(s) */
9656 ret = adev_update_voice_comm_input_stream(in, config);
9657 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009658
Revathi Uddarajud2634032017-12-07 14:42:34 +05309659 if (ret) {
9660 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9661 goto err_open;
9662 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009663 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309664
9665 /* assign concurrent capture usecase if record has to caried out from
9666 * actual hardware input source */
9667 if (audio_extn_is_concurrent_capture_enabled() &&
9668 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309669 /* Acquire lock to avoid two concurrent use cases initialized to
9670 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009671
Samyak Jainc37062f2019-04-25 18:41:06 +05309672 if (in->usecase == USECASE_AUDIO_RECORD) {
9673 pthread_mutex_lock(&adev->lock);
9674 if (!(adev->pcm_record_uc_state)) {
9675 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9676 adev->pcm_record_uc_state = 1;
9677 pthread_mutex_unlock(&adev->lock);
9678 } else {
9679 pthread_mutex_unlock(&adev->lock);
9680 /* Assign compress record use case for second record */
9681 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9682 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9683 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9684 if (audio_extn_cin_applicable_stream(in)) {
9685 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309686 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309687 if (ret)
9688 goto err_open;
9689 }
9690 }
9691 }
kunleiz28c73e72019-03-27 17:24:04 +08009692 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009693 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309694 if (audio_extn_ssr_get_stream() != in)
9695 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009696
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009697 in->sample_rate = in->config.rate;
9698
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309699 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9700 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009701 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009702 in->sample_rate, in->bit_width,
9703 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309704 register_format(in->format, in->supported_formats);
9705 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9706 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309707
Aalique Grahame22e49102018-12-18 14:23:57 -08009708 in->error_log = error_log_create(
9709 ERROR_LOG_ENTRIES,
9710 1000000000 /* aggregate consecutive identical errors within one second */);
9711
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009712 /* This stream could be for sound trigger lab,
9713 get sound trigger pcm if present */
9714 audio_extn_sound_trigger_check_and_get_session(in);
9715
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309716 lock_input_stream(in);
9717 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9718 pthread_mutex_lock(&adev->lock);
9719 in->card_status = adev->card_status;
9720 pthread_mutex_unlock(&adev->lock);
9721 pthread_mutex_unlock(&in->lock);
9722
Aalique Grahame22e49102018-12-18 14:23:57 -08009723 stream_app_type_cfg_init(&in->app_type_cfg);
9724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009725 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009726
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009727 ret = io_streams_map_insert(adev, &in->stream.common,
9728 handle, AUDIO_PATCH_HANDLE_NONE);
9729 if (ret != 0)
9730 goto err_open;
9731
Susan Wang6dd13092021-01-25 10:27:11 -05009732 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009733
9734 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009735 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009736 pthread_mutex_unlock(&adev->lock);
9737
Eric Laurent994a6932013-07-17 11:51:42 -07009738 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009739 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009740
9741err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309742 if (in->usecase == USECASE_AUDIO_RECORD) {
9743 pthread_mutex_lock(&adev->lock);
9744 adev->pcm_record_uc_state = 0;
9745 pthread_mutex_unlock(&adev->lock);
9746 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009747 free(in);
9748 *stream_in = NULL;
9749 return ret;
9750}
9751
9752static void adev_close_input_stream(struct audio_hw_device *dev,
9753 struct audio_stream_in *stream)
9754{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009755 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009756 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009757 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309758
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309759 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009760
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009761 if (in == NULL) {
9762 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9763 return;
9764 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009765 io_streams_map_remove(adev, in->capture_handle);
9766
Susan Wang6dd13092021-01-25 10:27:11 -05009767 // remove out_ctxt early to prevent the stream
9768 // being opened in a race condition
9769 pthread_mutex_lock(&adev->lock);
9770 list_remove(&in->in_ctxt.list);
9771 pthread_mutex_unlock(&adev->lock);
9772
kunleiz70e57612018-12-28 17:50:23 +08009773 /* must deregister from sndmonitor first to prevent races
9774 * between the callback and close_stream
9775 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309776 audio_extn_snd_mon_unregister_listener(stream);
9777
kunleiz70e57612018-12-28 17:50:23 +08009778 /* Disable echo reference if there are no active input, hfp call
9779 * and sound trigger while closing input stream
9780 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009781 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009782 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009783 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9784 struct listnode out_devices;
9785 list_init(&out_devices);
9786 platform_set_echo_reference(adev, false, &out_devices);
9787 } else
kunleiz70e57612018-12-28 17:50:23 +08009788 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309789
Weiyin Jiang2995f662019-04-17 14:25:12 +08009790 error_log_destroy(in->error_log);
9791 in->error_log = NULL;
9792
Pallavid7c7a272018-01-16 11:22:55 +05309793
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009794 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309795 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009796 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309797 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009798 if (ret != 0)
9799 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9800 __func__, ret);
9801 } else
9802 in_standby(&stream->common);
9803
Weiyin Jiang280ea742020-09-08 20:28:22 +08009804 pthread_mutex_destroy(&in->lock);
9805 pthread_mutex_destroy(&in->pre_lock);
9806
Revathi Uddarajud2634032017-12-07 14:42:34 +05309807 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309808 if (in->usecase == USECASE_AUDIO_RECORD) {
9809 adev->pcm_record_uc_state = 0;
9810 }
9811
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009812 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9813 adev->enable_voicerx = false;
9814 }
9815
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009816 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009817 audio_extn_ssr_deinit();
9818 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009819
Garmond Leunge2433c32017-09-28 21:51:22 -07009820 if (audio_extn_ffv_get_stream() == in) {
9821 audio_extn_ffv_stream_deinit();
9822 }
9823
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309824 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009825 audio_extn_compr_cap_format_supported(in->config.format))
9826 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309827
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309828 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309829 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009830
Mingming Yinfd7607b2016-01-22 12:48:44 -08009831 if (in->is_st_session) {
9832 ALOGV("%s: sound trigger pcm stop lab", __func__);
9833 audio_extn_sound_trigger_stop_lab(in);
9834 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009835 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309836 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009837 return;
9838}
9839
Aalique Grahame22e49102018-12-18 14:23:57 -08009840/* verifies input and output devices and their capabilities.
9841 *
9842 * This verification is required when enabling extended bit-depth or
9843 * sampling rates, as not all qcom products support it.
9844 *
9845 * Suitable for calling only on initialization such as adev_open().
9846 * It fills the audio_device use_case_table[] array.
9847 *
9848 * Has a side-effect that it needs to configure audio routing / devices
9849 * in order to power up the devices and read the device parameters.
9850 * It does not acquire any hw device lock. Should restore the devices
9851 * back to "normal state" upon completion.
9852 */
9853static int adev_verify_devices(struct audio_device *adev)
9854{
9855 /* enumeration is a bit difficult because one really wants to pull
9856 * the use_case, device id, etc from the hidden pcm_device_table[].
9857 * In this case there are the following use cases and device ids.
9858 *
9859 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9860 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9861 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9862 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9863 * [USECASE_AUDIO_RECORD] = {0, 0},
9864 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9865 * [USECASE_VOICE_CALL] = {2, 2},
9866 *
9867 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9868 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9869 */
9870
9871 /* should be the usecases enabled in adev_open_input_stream() */
9872 static const int test_in_usecases[] = {
9873 USECASE_AUDIO_RECORD,
9874 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9875 };
9876 /* should be the usecases enabled in adev_open_output_stream()*/
9877 static const int test_out_usecases[] = {
9878 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9879 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9880 };
9881 static const usecase_type_t usecase_type_by_dir[] = {
9882 PCM_PLAYBACK,
9883 PCM_CAPTURE,
9884 };
9885 static const unsigned flags_by_dir[] = {
9886 PCM_OUT,
9887 PCM_IN,
9888 };
9889
9890 size_t i;
9891 unsigned dir;
9892 const unsigned card_id = adev->snd_card;
9893
9894 for (dir = 0; dir < 2; ++dir) {
9895 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9896 const unsigned flags_dir = flags_by_dir[dir];
9897 const size_t testsize =
9898 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9899 const int *testcases =
9900 dir ? test_in_usecases : test_out_usecases;
9901 const audio_devices_t audio_device =
9902 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9903
9904 for (i = 0; i < testsize; ++i) {
9905 const audio_usecase_t audio_usecase = testcases[i];
9906 int device_id;
9907 struct pcm_params **pparams;
9908 struct stream_out out;
9909 struct stream_in in;
9910 struct audio_usecase uc_info;
9911 int retval;
9912
9913 pparams = &adev->use_case_table[audio_usecase];
9914 pcm_params_free(*pparams); /* can accept null input */
9915 *pparams = NULL;
9916
9917 /* find the device ID for the use case (signed, for error) */
9918 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9919 if (device_id < 0)
9920 continue;
9921
9922 /* prepare structures for device probing */
9923 memset(&uc_info, 0, sizeof(uc_info));
9924 uc_info.id = audio_usecase;
9925 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009926 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009927 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009928 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009929 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009930 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009931 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9932 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009933 }
9934 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009935 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009936 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009937 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009938 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009939 uc_info.in_snd_device = SND_DEVICE_NONE;
9940 uc_info.out_snd_device = SND_DEVICE_NONE;
9941 list_add_tail(&adev->usecase_list, &uc_info.list);
9942
9943 /* select device - similar to start_(in/out)put_stream() */
9944 retval = select_devices(adev, audio_usecase);
9945 if (retval >= 0) {
9946 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9947#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009948 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009949 if (*pparams) {
9950 ALOGV("%s: (%s) card %d device %d", __func__,
9951 dir ? "input" : "output", card_id, device_id);
9952 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9953 } else {
9954 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9955 }
9956#endif
9957 }
9958
9959 /* deselect device - similar to stop_(in/out)put_stream() */
9960 /* 1. Get and set stream specific mixer controls */
9961 retval = disable_audio_route(adev, &uc_info);
9962 /* 2. Disable the rx device */
9963 retval = disable_snd_device(adev,
9964 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9965 list_remove(&uc_info.list);
9966 }
9967 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009968 return 0;
9969}
9970
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009971int update_patch(unsigned int num_sources,
9972 const struct audio_port_config *sources,
9973 unsigned int num_sinks,
9974 const struct audio_port_config *sinks,
9975 audio_patch_handle_t handle,
9976 struct audio_patch_info *p_info,
9977 patch_type_t patch_type, bool new_patch)
9978{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009979 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009980
9981 if (p_info == NULL) {
9982 ALOGE("%s: Invalid patch pointer", __func__);
9983 return -EINVAL;
9984 }
9985
9986 if (new_patch) {
9987 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9988 if (p_info->patch == NULL) {
9989 ALOGE("%s: Could not allocate patch", __func__);
9990 return -ENOMEM;
9991 }
9992 }
9993
9994 p_info->patch->id = handle;
9995 p_info->patch->num_sources = num_sources;
9996 p_info->patch->num_sinks = num_sinks;
9997
9998 for (int i = 0; i < num_sources; i++)
9999 p_info->patch->sources[i] = sources[i];
10000 for (int i = 0; i < num_sinks; i++)
10001 p_info->patch->sinks[i] = sinks[i];
10002
10003 p_info->patch_type = patch_type;
10004 return 0;
10005}
10006
10007audio_patch_handle_t generate_patch_handle()
10008{
10009 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10010 if (++patch_handle < 0)
10011 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10012 return patch_handle;
10013}
10014
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010015int adev_create_audio_patch(struct audio_hw_device *dev,
10016 unsigned int num_sources,
10017 const struct audio_port_config *sources,
10018 unsigned int num_sinks,
10019 const struct audio_port_config *sinks,
10020 audio_patch_handle_t *handle)
10021{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010022 int ret = 0;
10023 struct audio_device *adev = (struct audio_device *)dev;
10024 struct audio_patch_info *p_info = NULL;
10025 patch_type_t patch_type = PATCH_NONE;
10026 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10027 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10028 struct audio_stream_info *s_info = NULL;
10029 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010030 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010031 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10032 bool new_patch = false;
10033 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010034
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10036 num_sources, num_sinks, *handle);
10037
10038 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10039 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10040 ALOGE("%s: Invalid patch arguments", __func__);
10041 ret = -EINVAL;
10042 goto done;
10043 }
10044
10045 if (num_sources > 1) {
10046 ALOGE("%s: Multiple sources are not supported", __func__);
10047 ret = -EINVAL;
10048 goto done;
10049 }
10050
10051 if (sources == NULL || sinks == NULL) {
10052 ALOGE("%s: Invalid sources or sinks port config", __func__);
10053 ret = -EINVAL;
10054 goto done;
10055 }
10056
10057 ALOGV("%s: source role %d, source type %d", __func__,
10058 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010059 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060
10061 // Populate source/sink information and fetch stream info
10062 switch (sources[0].type) {
10063 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10064 device_type = sources[0].ext.device.type;
10065 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010066 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010067 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10068 patch_type = PATCH_CAPTURE;
10069 io_handle = sinks[0].ext.mix.handle;
10070 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010071 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 __func__, device_type, io_handle);
10073 } else {
10074 // Device to device patch is not implemented.
10075 // This space will need changes if audio HAL
10076 // handles device to device patches in the future.
10077 patch_type = PATCH_DEVICE_LOOPBACK;
10078 }
10079 break;
10080 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10081 io_handle = sources[0].ext.mix.handle;
10082 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010083 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010084 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010085 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086 }
10087 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010088 ALOGD("%s: Playback patch from mix handle %d to device %x",
10089 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010090 break;
10091 case AUDIO_PORT_TYPE_SESSION:
10092 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010093 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10094 ret = -EINVAL;
10095 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010096 }
10097
10098 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010099
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 // Generate patch info and update patch
10101 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010102 *handle = generate_patch_handle();
10103 p_info = (struct audio_patch_info *)
10104 calloc(1, sizeof(struct audio_patch_info));
10105 if (p_info == NULL) {
10106 ALOGE("%s: Failed to allocate memory", __func__);
10107 pthread_mutex_unlock(&adev->lock);
10108 ret = -ENOMEM;
10109 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010110 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010111 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010112 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010113 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010114 if (p_info == NULL) {
10115 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10116 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010117 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010118 ret = -EINVAL;
10119 goto done;
10120 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010121 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010122 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010123 *handle, p_info, patch_type, new_patch);
10124
10125 // Fetch stream info of associated mix for playback or capture patches
10126 if (p_info->patch_type == PATCH_PLAYBACK ||
10127 p_info->patch_type == PATCH_CAPTURE) {
10128 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10129 if (s_info == NULL) {
10130 ALOGE("%s: Failed to obtain stream info", __func__);
10131 if (new_patch)
10132 free(p_info);
10133 pthread_mutex_unlock(&adev->lock);
10134 ret = -EINVAL;
10135 goto done;
10136 }
10137 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10138 s_info->patch_handle = *handle;
10139 stream = s_info->stream;
10140 }
10141 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010142
10143 // Update routing for stream
10144 if (stream != NULL) {
10145 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010146 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010148 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010149 if (ret < 0) {
10150 pthread_mutex_lock(&adev->lock);
10151 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10152 if (new_patch)
10153 free(p_info);
10154 pthread_mutex_unlock(&adev->lock);
10155 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10156 goto done;
10157 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010158 }
10159
10160 // Add new patch to patch map
10161 if (!ret && new_patch) {
10162 pthread_mutex_lock(&adev->lock);
10163 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010164 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010165 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010166 }
10167
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010168done:
10169 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010170 num_sources,
10171 sources,
10172 num_sinks,
10173 sinks,
10174 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010176 num_sources,
10177 sources,
10178 num_sinks,
10179 sinks,
10180 handle);
10181 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010182}
10183
10184int adev_release_audio_patch(struct audio_hw_device *dev,
10185 audio_patch_handle_t handle)
10186{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 struct audio_device *adev = (struct audio_device *) dev;
10188 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010189 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010190 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010191
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010192 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10193 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10194 ret = -EINVAL;
10195 goto done;
10196 }
10197
10198 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010199 pthread_mutex_lock(&adev->lock);
10200 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010201 if (p_info == NULL) {
10202 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010203 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010204 ret = -EINVAL;
10205 goto done;
10206 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010207 struct audio_patch *patch = p_info->patch;
10208 if (patch == NULL) {
10209 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010210 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212 goto done;
10213 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010214 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10215 switch (patch->sources[0].type) {
10216 case AUDIO_PORT_TYPE_MIX:
10217 io_handle = patch->sources[0].ext.mix.handle;
10218 break;
10219 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010220 if (p_info->patch_type == PATCH_CAPTURE)
10221 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010222 break;
10223 case AUDIO_PORT_TYPE_SESSION:
10224 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010225 pthread_mutex_unlock(&adev->lock);
10226 ret = -EINVAL;
10227 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010228 }
10229
10230 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010231 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010232 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010233 if (patch_type == PATCH_PLAYBACK ||
10234 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010235 struct audio_stream_info *s_info =
10236 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10237 if (s_info == NULL) {
10238 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10239 pthread_mutex_unlock(&adev->lock);
10240 goto done;
10241 }
10242 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10243 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010244 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010245 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010246
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010247 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010248 struct listnode devices;
10249 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010250 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010251 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010252 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010253 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010254 }
10255
10256 if (ret < 0)
10257 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10258
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010259done:
10260 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10261 audio_extn_auto_hal_release_audio_patch(dev, handle);
10262
10263 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010264 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010265}
10266
10267int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10268{
Derek Chenf13dd492018-11-13 14:53:51 -080010269 int ret = 0;
10270
10271 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10272 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10273 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010274}
10275
10276int adev_set_audio_port_config(struct audio_hw_device *dev,
10277 const struct audio_port_config *config)
10278{
Derek Chenf13dd492018-11-13 14:53:51 -080010279 int ret = 0;
10280
10281 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10282 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10283 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010284}
10285
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010286static int adev_dump(const audio_hw_device_t *device __unused,
10287 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010288{
10289 return 0;
10290}
10291
10292static int adev_close(hw_device_t *device)
10293{
Aalique Grahame22e49102018-12-18 14:23:57 -080010294 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010295 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010296
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010297 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010298 return 0;
10299
10300 pthread_mutex_lock(&adev_init_lock);
10301
10302 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010303 if (audio_extn_spkr_prot_is_enabled())
10304 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010305 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010306 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010307 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010308 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010309 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010310 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010311 audio_extn_utils_release_streams_cfg_lists(
10312 &adev->streams_output_cfg_list,
10313 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010314 if (audio_extn_qap_is_enabled())
10315 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010316 if (audio_extn_qaf_is_enabled())
10317 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010318 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010319 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010320 free(adev->snd_dev_ref_cnt);
10321 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010322 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10323 pcm_params_free(adev->use_case_table[i]);
10324 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010325 if (adev->adm_deinit)
10326 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010327 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010328 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010329 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010330 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010331 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010332 if (adev->device_cfg_params) {
10333 free(adev->device_cfg_params);
10334 adev->device_cfg_params = NULL;
10335 }
Derek Chend2530072014-11-24 12:39:14 -080010336 if(adev->ext_hw_plugin)
10337 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010338 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010339 free_map(adev->patch_map);
10340 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010341 free(device);
10342 adev = NULL;
10343 }
10344 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010345 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010346 return 0;
10347}
10348
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010349/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10350 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10351 * just that it _might_ work.
10352 */
10353static int period_size_is_plausible_for_low_latency(int period_size)
10354{
10355 switch (period_size) {
10356 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010357 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010358 case 240:
10359 case 320:
10360 case 480:
10361 return 1;
10362 default:
10363 return 0;
10364 }
10365}
10366
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010367static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10368{
10369 bool is_snd_card_status = false;
10370 bool is_ext_device_status = false;
10371 char value[32];
10372 int card = -1;
10373 card_status_t status;
10374
10375 if (cookie != adev || !parms)
10376 return;
10377
10378 if (!parse_snd_card_status(parms, &card, &status)) {
10379 is_snd_card_status = true;
10380 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10381 is_ext_device_status = true;
10382 } else {
10383 // not a valid event
10384 return;
10385 }
10386
10387 pthread_mutex_lock(&adev->lock);
10388 if (card == adev->snd_card || is_ext_device_status) {
10389 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010390 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010391 adev->card_status = status;
10392 platform_snd_card_update(adev->platform, status);
10393 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010394 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010395 if (status == CARD_STATUS_OFFLINE)
10396 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010397 } else if (is_ext_device_status) {
10398 platform_set_parameters(adev->platform, parms);
10399 }
10400 }
10401 pthread_mutex_unlock(&adev->lock);
10402 return;
10403}
10404
Weiyin Jiang280ea742020-09-08 20:28:22 +080010405/* adev lock held */
10406int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010407{
10408 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010409 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010410 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010411 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010412
10413 uc_info = get_usecase_from_list(adev, out->usecase);
10414 if (uc_info == NULL) {
10415 ALOGE("%s: Could not find the usecase (%d) in the list",
10416 __func__, out->usecase);
10417 return -EINVAL;
10418 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010419 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010420
Zhou Songbaddf9f2020-11-20 13:57:39 +080010421 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10422 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010423
10424 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010425 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010426 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010427 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010428 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010429 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10430 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010431
10432 if (is_offload_usecase(out->usecase)) {
10433 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010434 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010435 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10436 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10437 } else {
10438 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010439 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010440 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010441 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010442 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010443 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010444 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010445 // mute stream and switch to speaker if suspended
10446 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010447 assign_devices(&devices, &out->device_list);
10448 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010449 list_for_each(node, &adev->usecase_list) {
10450 usecase = node_to_item(node, struct audio_usecase, list);
10451 if ((usecase != uc_info) &&
10452 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10453 usecase->out_snd_device)) {
10454 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10455 break;
10456 }
10457 }
Zhou Song8edbbdb2021-01-14 16:48:03 +080010458 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP) {
10459 out->a2dp_muted = true;
10460 if (is_offload_usecase(out->usecase)) {
10461 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10462 compress_pause(out->compr);
10463 out_set_compr_volume(&out->stream, (float)0, (float)0);
10464 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10465 out_set_voip_volume(&out->stream, (float)0, (float)0);
10466 } else {
10467 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10468 /* wait for stale pcm drained before switching to speaker */
10469 uint32_t latency =
10470 (out->config.period_count * out->config.period_size * 1000) /
10471 (out->config.rate);
10472 usleep(latency * 1000);
10473 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010474 }
10475 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010476 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10477 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010478 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010479 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10480 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010482 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010483 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010484 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010485 }
10486 ALOGV("%s: exit", __func__);
10487 return 0;
10488}
10489
Haynes Mathew George01156f92018-04-13 15:29:54 -070010490void adev_on_battery_status_changed(bool charging)
10491{
10492 pthread_mutex_lock(&adev->lock);
10493 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10494 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010495 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010496 pthread_mutex_unlock(&adev->lock);
10497}
10498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010499static int adev_open(const hw_module_t *module, const char *name,
10500 hw_device_t **device)
10501{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010502 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010503 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010504 char mixer_ctl_name[128] = {0};
10505 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010506
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010507 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010508 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10509
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010510 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010511 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010512 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010513 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010514 ALOGD("%s: returning existing instance of adev", __func__);
10515 ALOGD("%s: exit", __func__);
10516 pthread_mutex_unlock(&adev_init_lock);
10517 return 0;
10518 }
10519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010520 adev = calloc(1, sizeof(struct audio_device));
10521
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010522 if (!adev) {
10523 pthread_mutex_unlock(&adev_init_lock);
10524 return -ENOMEM;
10525 }
10526
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010527 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10528
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010529 // register audio ext hidl at the earliest
10530 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010531#ifdef DYNAMIC_LOG_ENABLED
10532 register_for_dynamic_logging("hal");
10533#endif
10534
Derek Chenf939fb72018-11-13 13:34:41 -080010535 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010536 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010537 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10538 maj_version = atoi(value);
10539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010540 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010541 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010542 adev->device.common.module = (struct hw_module_t *)module;
10543 adev->device.common.close = adev_close;
10544
10545 adev->device.init_check = adev_init_check;
10546 adev->device.set_voice_volume = adev_set_voice_volume;
10547 adev->device.set_master_volume = adev_set_master_volume;
10548 adev->device.get_master_volume = adev_get_master_volume;
10549 adev->device.set_master_mute = adev_set_master_mute;
10550 adev->device.get_master_mute = adev_get_master_mute;
10551 adev->device.set_mode = adev_set_mode;
10552 adev->device.set_mic_mute = adev_set_mic_mute;
10553 adev->device.get_mic_mute = adev_get_mic_mute;
10554 adev->device.set_parameters = adev_set_parameters;
10555 adev->device.get_parameters = adev_get_parameters;
10556 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10557 adev->device.open_output_stream = adev_open_output_stream;
10558 adev->device.close_output_stream = adev_close_output_stream;
10559 adev->device.open_input_stream = adev_open_input_stream;
10560 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010561 adev->device.create_audio_patch = adev_create_audio_patch;
10562 adev->device.release_audio_patch = adev_release_audio_patch;
10563 adev->device.get_audio_port = adev_get_audio_port;
10564 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010565 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010566 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010567
10568 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010569 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010570 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010571 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010572 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010573 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010574 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010575 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010576 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010577 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010578 /* Init audio and voice feature */
10579 audio_extn_feature_init();
10580 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010581 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010582 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010583 list_init(&adev->active_inputs_list);
10584 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010585 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010586 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10587 audio_extn_utils_hash_eq);
10588 if (!adev->io_streams_map) {
10589 ALOGE("%s: Could not create io streams map", __func__);
10590 ret = -ENOMEM;
10591 goto adev_open_err;
10592 }
10593 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10594 audio_extn_utils_hash_eq);
10595 if (!adev->patch_map) {
10596 ALOGE("%s: Could not create audio patch map", __func__);
10597 ret = -ENOMEM;
10598 goto adev_open_err;
10599 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010600 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010601 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010602 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010603 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010604 adev->perf_lock_opts[0] = 0x101;
10605 adev->perf_lock_opts[1] = 0x20E;
10606 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010607 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010608 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010609 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010610 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010611 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010612
Zhou Song68ebc352019-12-05 17:11:15 +080010613 audio_extn_perf_lock_init();
10614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010615 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010616 adev->platform = platform_init(adev);
10617 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010618 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010619 ret = -EINVAL;
10620 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010621 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010622
Aalique Grahame22e49102018-12-18 14:23:57 -080010623 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010624 if (audio_extn_qap_is_enabled()) {
10625 ret = audio_extn_qap_init(adev);
10626 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010627 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010628 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010629 }
10630 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10631 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10632 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010633
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010634 if (audio_extn_qaf_is_enabled()) {
10635 ret = audio_extn_qaf_init(adev);
10636 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010637 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010638 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010639 }
10640
10641 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10642 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10643 }
10644
Derek Chenae7b0342019-02-08 15:17:04 -080010645 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010646 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10647
Eric Laurentc4aef752013-09-12 17:45:53 -070010648 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10649 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10650 if (adev->visualizer_lib == NULL) {
10651 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10652 } else {
10653 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10654 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010655 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010656 "visualizer_hal_start_output");
10657 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010658 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010659 "visualizer_hal_stop_output");
10660 }
10661 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010662 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010663 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010664 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010665 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010666 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010667 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010668
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010669 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10670 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10671 if (adev->offload_effects_lib == NULL) {
10672 ALOGE("%s: DLOPEN failed for %s", __func__,
10673 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10674 } else {
10675 ALOGV("%s: DLOPEN successful for %s", __func__,
10676 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10677 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010678 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010679 "offload_effects_bundle_hal_start_output");
10680 adev->offload_effects_stop_output =
10681 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10682 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010683 adev->offload_effects_set_hpx_state =
10684 (int (*)(bool))dlsym(adev->offload_effects_lib,
10685 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010686 adev->offload_effects_get_parameters =
10687 (void (*)(struct str_parms *, struct str_parms *))
10688 dlsym(adev->offload_effects_lib,
10689 "offload_effects_bundle_get_parameters");
10690 adev->offload_effects_set_parameters =
10691 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10692 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010693 }
10694 }
10695
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010696 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10697 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10698 if (adev->adm_lib == NULL) {
10699 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10700 } else {
10701 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10702 adev->adm_init = (adm_init_t)
10703 dlsym(adev->adm_lib, "adm_init");
10704 adev->adm_deinit = (adm_deinit_t)
10705 dlsym(adev->adm_lib, "adm_deinit");
10706 adev->adm_register_input_stream = (adm_register_input_stream_t)
10707 dlsym(adev->adm_lib, "adm_register_input_stream");
10708 adev->adm_register_output_stream = (adm_register_output_stream_t)
10709 dlsym(adev->adm_lib, "adm_register_output_stream");
10710 adev->adm_deregister_stream = (adm_deregister_stream_t)
10711 dlsym(adev->adm_lib, "adm_deregister_stream");
10712 adev->adm_request_focus = (adm_request_focus_t)
10713 dlsym(adev->adm_lib, "adm_request_focus");
10714 adev->adm_abandon_focus = (adm_abandon_focus_t)
10715 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010716 adev->adm_set_config = (adm_set_config_t)
10717 dlsym(adev->adm_lib, "adm_set_config");
10718 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10719 dlsym(adev->adm_lib, "adm_request_focus_v2");
10720 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10721 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10722 adev->adm_on_routing_change = (adm_on_routing_change_t)
10723 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010724 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10725 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010726 }
10727 }
10728
Aalique Grahame22e49102018-12-18 14:23:57 -080010729 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010730 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010731 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010732 //initialize this to false for now,
10733 //this will be set to true through set param
10734 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010735
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010736 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010737 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010738
10739 if (k_enable_extended_precision)
10740 adev_verify_devices(adev);
10741
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010742 adev->dsp_bit_width_enforce_mode =
10743 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010744
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010745 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10746 &adev->streams_output_cfg_list,
10747 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010748
Kiran Kandi910e1862013-10-29 13:29:42 -070010749 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010750
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010751 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010752 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010753 trial = atoi(value);
10754 if (period_size_is_plausible_for_low_latency(trial)) {
10755 pcm_config_low_latency.period_size = trial;
10756 pcm_config_low_latency.start_threshold = trial / 4;
10757 pcm_config_low_latency.avail_min = trial / 4;
10758 configured_low_latency_capture_period_size = trial;
10759 }
10760 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010761 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10762 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010763 trial = atoi(value);
10764 if (period_size_is_plausible_for_low_latency(trial)) {
10765 configured_low_latency_capture_period_size = trial;
10766 }
10767 }
10768
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010769 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10770
Eric Laurent4b084132018-10-19 17:33:43 -070010771 adev->camera_orientation = CAMERA_DEFAULT;
10772
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010773 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010774 af_period_multiplier = atoi(value);
10775 if (af_period_multiplier < 0)
10776 af_period_multiplier = 2;
10777 else if (af_period_multiplier > 4)
10778 af_period_multiplier = 4;
10779
10780 ALOGV("new period_multiplier = %d", af_period_multiplier);
10781 }
10782
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010783 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010784
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010785 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010786 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010787 pthread_mutex_unlock(&adev_init_lock);
10788
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010789 if (adev->adm_init)
10790 adev->adm_data = adev->adm_init();
10791
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010792 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010793 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010794
10795 audio_extn_snd_mon_init();
10796 pthread_mutex_lock(&adev->lock);
10797 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10798 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010799 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10800 /*
10801 * if the battery state callback happens before charging can be queried,
10802 * it will be guarded with the adev->lock held in the cb function and so
10803 * the callback value will reflect the latest state
10804 */
10805 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010806 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010807 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010808 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010809 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010810 /* Allocate memory for Device config params */
10811 adev->device_cfg_params = (struct audio_device_config_param*)
10812 calloc(platform_get_max_codec_backend(),
10813 sizeof(struct audio_device_config_param));
10814 if (adev->device_cfg_params == NULL)
10815 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010816
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010817 /*
10818 * Check if new PSPD matrix mixer control is supported. If not
10819 * supported, then set flag so that old mixer ctrl is sent while
10820 * sending pspd coefficients on older kernel version. Query mixer
10821 * control for default pcm id and channel value one.
10822 */
10823 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10824 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10825
10826 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10827 if (!ctl) {
10828 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10829 __func__, mixer_ctl_name);
10830 adev->use_old_pspd_mix_ctrl = true;
10831 }
10832
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010833 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010834 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010835
10836adev_open_err:
10837 free_map(adev->patch_map);
10838 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010839 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010840 pthread_mutex_destroy(&adev->lock);
10841 free(adev);
10842 adev = NULL;
10843 *device = NULL;
10844 pthread_mutex_unlock(&adev_init_lock);
10845 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010846}
10847
10848static struct hw_module_methods_t hal_module_methods = {
10849 .open = adev_open,
10850};
10851
10852struct audio_module HAL_MODULE_INFO_SYM = {
10853 .common = {
10854 .tag = HARDWARE_MODULE_TAG,
10855 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10856 .hal_api_version = HARDWARE_HAL_API_VERSION,
10857 .id = AUDIO_HARDWARE_MODULE_ID,
10858 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010859 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010860 .methods = &hal_module_methods,
10861 },
10862};