blob: 58eecd20fa60fd8cf9efb2a23505c87b98a31b73 [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 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -0700970 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
971 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
972 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
973 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
974 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
975 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
976 platform_check_and_set_codec_backend_cfg(adev, usecase,
977 usecase->out_snd_device);
978 }
979 }
Saurav Kumarc1411662020-10-14 10:50:45 +0530980 }
981 }
982}
983
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530984/*
985 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
986 * 44.1 or Native DSD backends are enabled for any of current use case.
987 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
988 * - Disable current mix path use case(Headphone backend) and re-enable it with
989 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
990 * e.g. Naitve DSD or Headphone 44.1 -> + 48
991 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530992static void check_and_set_asrc_mode(struct audio_device *adev,
993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530995{
996 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530997 int i, num_new_devices = 0;
998 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
999 /*
1000 *Split snd device for new combo use case
1001 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1002 */
1003 if (platform_split_snd_device(adev->platform,
1004 snd_device,
1005 &num_new_devices,
1006 split_new_snd_devices) == 0) {
1007 for (i = 0; i < num_new_devices; i++)
1008 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1009 } else {
1010 int new_backend_idx = platform_get_backend_index(snd_device);
1011 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1012 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1013 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1014 !adev->asrc_mode_enabled) {
1015 struct listnode *node = NULL;
1016 struct audio_usecase *uc = NULL;
1017 struct stream_out *curr_out = NULL;
1018 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1019 int i, num_devices, ret = 0;
1020 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301021
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301022 list_for_each(node, &adev->usecase_list) {
1023 uc = node_to_item(node, struct audio_usecase, list);
1024 curr_out = (struct stream_out*) uc->stream.out;
1025 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1026 /*
1027 *Split snd device for existing combo use case
1028 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1029 */
1030 ret = platform_split_snd_device(adev->platform,
1031 uc->out_snd_device,
1032 &num_devices,
1033 split_snd_devices);
1034 if (ret < 0 || num_devices == 0) {
1035 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1036 split_snd_devices[0] = uc->out_snd_device;
1037 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001038 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301039 for (i = 0; i < num_devices; i++) {
1040 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1041 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1042 if((new_backend_idx == HEADPHONE_BACKEND) &&
1043 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1044 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001045 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301046 __func__);
1047 enable_asrc_mode(adev);
1048 break;
1049 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1050 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1051 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001052 ALOGV("%s: 48K stream detected, disabling and enabling it \
1053 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301054 disable_audio_route(adev, uc);
1055 disable_snd_device(adev, uc->out_snd_device);
1056 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1057 if (new_backend_idx == DSD_NATIVE_BACKEND)
1058 audio_route_apply_and_update_path(adev->audio_route,
1059 "hph-true-highquality-mode");
1060 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1061 (curr_out->bit_width >= 24))
1062 audio_route_apply_and_update_path(adev->audio_route,
1063 "hph-highquality-mode");
1064 enable_asrc_mode(adev);
1065 enable_snd_device(adev, uc->out_snd_device);
1066 enable_audio_route(adev, uc);
1067 break;
1068 }
1069 }
1070 // reset split devices count
1071 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001072 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301073 if (adev->asrc_mode_enabled)
1074 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301075 }
1076 }
1077 }
1078}
1079
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001080static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1081 struct audio_effect_config effect_config,
1082 unsigned int param_value)
1083{
1084 char mixer_ctl_name[] = "Audio Effect";
1085 struct mixer_ctl *ctl;
1086 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001087 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001088
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001089 if (in == NULL) {
1090 ALOGE("%s: active input stream is NULL", __func__);
1091 return -EINVAL;
1092 }
1093
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001094 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1095 if (!ctl) {
1096 ALOGE("%s: Could not get mixer ctl - %s",
1097 __func__, mixer_ctl_name);
1098 return -EINVAL;
1099 }
1100
1101 set_values[0] = 1; //0:Rx 1:Tx
1102 set_values[1] = in->app_type_cfg.app_type;
1103 set_values[2] = (long)effect_config.module_id;
1104 set_values[3] = (long)effect_config.instance_id;
1105 set_values[4] = (long)effect_config.param_id;
1106 set_values[5] = param_value;
1107
1108 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1109
1110 return 0;
1111
1112}
1113
1114static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1115 int effect_type, unsigned int *param_value)
1116{
1117 int ret = 0;
1118 struct audio_effect_config other_effect_config;
1119 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001120 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001121
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001122 if (in == NULL) {
1123 ALOGE("%s: active input stream is NULL", __func__);
1124 return -EINVAL;
1125 }
1126
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001127 usecase = get_usecase_from_list(adev, in->usecase);
1128 if (!usecase)
1129 return -EINVAL;
1130
1131 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1132 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1133 if (ret < 0) {
1134 ALOGE("%s Failed to get effect params %d", __func__, ret);
1135 return ret;
1136 }
1137
1138 if (module_id == other_effect_config.module_id) {
1139 //Same module id for AEC/NS. Values need to be combined
1140 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1141 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1142 *param_value |= other_effect_config.param_value;
1143 }
1144 }
1145
1146 return ret;
1147}
1148
1149static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301150{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001151 struct audio_effect_config effect_config;
1152 struct audio_usecase *usecase = NULL;
1153 int ret = 0;
1154 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001155 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001157 if(!voice_extn_is_dynamic_ecns_enabled())
1158 return ENOSYS;
1159
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001160 if (!in) {
1161 ALOGE("%s: Invalid input stream", __func__);
1162 return -EINVAL;
1163 }
1164
1165 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1166
1167 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001168 if (usecase == NULL) {
1169 ALOGE("%s: Could not find the usecase (%d) in the list",
1170 __func__, in->usecase);
1171 return -EINVAL;
1172 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001173
1174 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1175 if (ret < 0) {
1176 ALOGE("%s Failed to get module id %d", __func__, ret);
1177 return ret;
1178 }
1179 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1180 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1181
1182 if(enable)
1183 param_value = effect_config.param_value;
1184
1185 /*Special handling for AEC & NS effects Param values need to be
1186 updated if module ids are same*/
1187
1188 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1189 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1190 if (ret < 0)
1191 return ret;
1192 }
1193
1194 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1195
1196 return ret;
1197}
1198
1199static void check_and_enable_effect(struct audio_device *adev)
1200{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001201 if(!voice_extn_is_dynamic_ecns_enabled())
1202 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001203
Eric Laurent637e2d42018-11-15 12:24:31 -08001204 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001205
Eric Laurent637e2d42018-11-15 12:24:31 -08001206 if (in != NULL && !in->standby) {
1207 if (in->enable_aec)
1208 enable_disable_effect(adev, EFFECT_AEC, true);
1209
1210 if (in->enable_ns &&
1211 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1212 enable_disable_effect(adev, EFFECT_NS, true);
1213 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001214 }
1215}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001216
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001217int pcm_ioctl(struct pcm *pcm, int request, ...)
1218{
1219 va_list ap;
1220 void * arg;
1221 int pcm_fd = *(int*)pcm;
1222
1223 va_start(ap, request);
1224 arg = va_arg(ap, void *);
1225 va_end(ap);
1226
1227 return ioctl(pcm_fd, request, arg);
1228}
1229
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001230int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001231 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001233 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001234 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301235 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301236 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001237 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301238 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001239
1240 if (usecase == NULL)
1241 return -EINVAL;
1242
1243 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1244
Carter Hsu2e429db2019-05-14 18:50:52 +08001245 if (usecase->type == PCM_CAPTURE) {
1246 struct stream_in *in = usecase->stream.in;
1247 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001248 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001249
1250 if (in) {
1251 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001252 list_init(&out_devices);
1253 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001254 struct listnode *node;
1255 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1256 USECASE_AUDIO_PLAYBACK_VOIP);
1257 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001258 assign_devices(&out_devices,
1259 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001260 } else if (adev->primary_output &&
1261 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001262 assign_devices(&out_devices,
1263 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001264 } else {
1265 list_for_each(node, &adev->usecase_list) {
1266 uinfo = node_to_item(node, struct audio_usecase, list);
1267 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001268 assign_devices(&out_devices,
1269 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001270 break;
1271 }
1272 }
1273 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001274
1275 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001276 in->ec_opened = true;
1277 }
1278 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001279 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1280 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1281 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001282 snd_device = usecase->in_snd_device;
1283 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001285 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001286
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001287 if (usecase->type == PCM_CAPTURE) {
1288 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1289 platform_set_fluence_nn_state(adev->platform, true);
1290 ALOGD("%s: set fluence nn capture state", __func__);
1291 }
1292 }
1293
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001294#ifdef DS1_DOLBY_DAP_ENABLED
1295 audio_extn_dolby_set_dmid(adev);
1296 audio_extn_dolby_set_endpoint(adev);
1297#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001298 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001299 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301300 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001301 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001302 if (audio_extn_is_maxx_audio_enabled())
1303 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301304 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001305 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1306 out = usecase->stream.out;
1307 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301308 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1309 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301310
1311 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001312 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1313 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1314 adev->fluence_nn_usecase_id = usecase->id;
1315 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1316 }
1317 }
1318
1319 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301320 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001321 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301322 ALOGD("%s: set custom mtmx params v1", __func__);
1323 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1324 }
1325 } else {
1326 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1327 }
Manish Dewangan58229382017-02-02 15:48:41 +05301328
Andy Hung756ecc12018-10-19 17:47:12 -07001329 // we shouldn't truncate mixer_path
1330 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1331 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1332 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001333 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001334 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301335 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1336 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1337 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1338 if (parms) {
1339 audio_extn_fm_set_parameters(adev, parms);
1340 str_parms_destroy(parms);
1341 }
1342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 ALOGV("%s: exit", __func__);
1344 return 0;
1345}
1346
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001347int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001348 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001351 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301352 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001353
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301354 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001355 return -EINVAL;
1356
1357 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301358 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 snd_device = usecase->in_snd_device;
1360 else
1361 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001362
1363 /* disable island and power mode on supported device for voice call */
1364 if (usecase->type == VOICE_CALL) {
1365 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1366 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1367 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1368 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1369 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1370 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001371 if (voice_is_lte_call_active(adev))
1372 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001373 ALOGD("%s: disable island cfg and power mode in voice tx path",
1374 __func__);
1375 }
1376 }
1377 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1378 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1379 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1380 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1381 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1382 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1383 ALOGD("%s: disable island cfg and power mode in voice rx path",
1384 __func__);
1385 }
1386 }
1387 }
1388
Andy Hung756ecc12018-10-19 17:47:12 -07001389 // we shouldn't truncate mixer_path
1390 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1391 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1392 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001393 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001394 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001395 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001396 if (usecase->type == PCM_CAPTURE) {
1397 struct stream_in *in = usecase->stream.in;
1398 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001399 struct listnode out_devices;
1400 list_init(&out_devices);
1401 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001402 in->ec_opened = false;
1403 }
1404 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001405 if (usecase->id == adev->fluence_nn_usecase_id) {
1406 platform_set_fluence_nn_state(adev->platform, false);
1407 adev->fluence_nn_usecase_id = USECASE_INVALID;
1408 ALOGD("%s: reset fluence nn capture state", __func__);
1409 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001410 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301411 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301412
1413 if (usecase->type == PCM_CAPTURE) {
1414 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001415 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301416 ALOGD("%s: reset custom mtmx params v1", __func__);
1417 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1418 }
1419 } else {
1420 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1421 }
1422
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001423 if ((usecase->type == PCM_PLAYBACK) &&
1424 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301425 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 ALOGV("%s: exit", __func__);
1428 return 0;
1429}
1430
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001431int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001432 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301434 int i, num_devices = 0;
1435 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001436 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1437
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001438 if (snd_device < SND_DEVICE_MIN ||
1439 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001440 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001441 return -EINVAL;
1442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001445 ALOGE("%s: Invalid sound device returned", __func__);
1446 return -EINVAL;
1447 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001448
1449 adev->snd_dev_ref_cnt[snd_device]++;
1450
1451 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1452 (platform_split_snd_device(adev->platform,
1453 snd_device,
1454 &num_devices,
1455 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001456 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001457 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001458 /* Set backend config for A2DP to ensure slimbus configuration
1459 is correct if A2DP is already active and backend is closed
1460 and re-opened */
1461 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1462 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 return 0;
1464 }
1465
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001466 if (audio_extn_spkr_prot_is_enabled())
1467 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001468
Aalique Grahame22e49102018-12-18 14:23:57 -08001469 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1470
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001471 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1472 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001473 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1474 goto err;
1475 }
1476 audio_extn_dev_arbi_acquire(snd_device);
1477 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001478 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001479 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001480 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001481 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001482 } else if (platform_split_snd_device(adev->platform,
1483 snd_device,
1484 &num_devices,
1485 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 for (i = 0; i < num_devices; i++) {
1487 enable_snd_device(adev, new_snd_devices[i]);
1488 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001489 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001490 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001491 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301492
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001493 /* enable island and power mode on supported device */
1494 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1495 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1496 platform_set_island_cfg_on_device(adev, snd_device, true);
1497 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001498 if (voice_is_lte_call_active(adev) &&
1499 (snd_device >= SND_DEVICE_IN_BEGIN &&
1500 snd_device < SND_DEVICE_IN_END))
1501 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001502 ALOGD("%s: enable island cfg and power mode on: %s",
1503 __func__, device_name);
1504 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301505
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301506 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1507 if (audio_extn_a2dp_start_playback() < 0) {
1508 ALOGE(" fail to configure A2dp Source control path ");
1509 goto err;
1510 } else {
1511 adev->a2dp_started = true;
1512 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001514
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001515 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1516 (audio_extn_a2dp_start_capture() < 0)) {
1517 ALOGE(" fail to configure A2dp Sink control path ");
1518 goto err;
1519 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301520
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001521 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1522 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1523 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1524 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1525 ALOGE(" fail to configure sco control path ");
1526 goto err;
1527 }
Zhou Song12c29502019-03-16 10:37:18 +08001528 }
1529
Zhou Song331c8e52019-08-26 14:16:12 +08001530 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001531 /* due to the possibility of calibration overwrite between listen
1532 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001533 audio_extn_sound_trigger_update_device_status(snd_device,
1534 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301535 audio_extn_listen_update_device_status(snd_device,
1536 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001537 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001538 audio_extn_sound_trigger_update_device_status(snd_device,
1539 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301540 audio_extn_listen_update_device_status(snd_device,
1541 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001542 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001543 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001544 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001545 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301546
1547 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1548 !adev->native_playback_enabled &&
1549 audio_is_true_native_stream_active(adev)) {
1550 ALOGD("%s: %d: napb: enabling native mode in hardware",
1551 __func__, __LINE__);
1552 audio_route_apply_and_update_path(adev->audio_route,
1553 "true-native-mode");
1554 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301555 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301556 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1557 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001558 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001559 ALOGD("%s: init ec ref loopback", __func__);
1560 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001564err:
1565 adev->snd_dev_ref_cnt[snd_device]--;
1566 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567}
1568
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001569int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001570 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301572 int i, num_devices = 0;
1573 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001574 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1575
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001576 if (snd_device < SND_DEVICE_MIN ||
1577 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001578 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001579 return -EINVAL;
1580 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001581
1582 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1583 ALOGE("%s: Invalid sound device returned", __func__);
1584 return -EINVAL;
1585 }
1586
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1588 ALOGE("%s: device ref cnt is already 0", __func__);
1589 return -EINVAL;
1590 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001591
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001593
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001595 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001596 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301597
Aalique Grahame22e49102018-12-18 14:23:57 -08001598 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1599
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001600 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1601 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001602 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001603
1604 // when speaker device is disabled, reset swap.
1605 // will be renabled on usecase start
1606 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001607 } else if (platform_split_snd_device(adev->platform,
1608 snd_device,
1609 &num_devices,
1610 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301611 for (i = 0; i < num_devices; i++) {
1612 disable_snd_device(adev, new_snd_devices[i]);
1613 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001614 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001615 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001616 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001617 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001618
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301619 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301620 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301621 adev->a2dp_started = false;
1622 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001623 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001624 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001625 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301626 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001627 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301628 adev->native_playback_enabled) {
1629 ALOGD("%s: %d: napb: disabling native mode in hardware",
1630 __func__, __LINE__);
1631 audio_route_reset_and_update_path(adev->audio_route,
1632 "true-native-mode");
1633 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001634 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301635 adev->asrc_mode_enabled) {
1636 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301637 disable_asrc_mode(adev);
1638 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001639 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301640 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001641 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001642 ALOGD("%s: deinit ec ref loopback", __func__);
1643 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1644 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001645
1646 audio_extn_utils_release_snd_device(snd_device);
1647 } else {
1648 if (platform_split_snd_device(adev->platform,
1649 snd_device,
1650 &num_devices,
1651 new_snd_devices) == 0) {
1652 for (i = 0; i < num_devices; i++) {
1653 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1654 }
1655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001656 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 return 0;
1659}
1660
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001661/*
1662 legend:
1663 uc - existing usecase
1664 new_uc - new usecase
1665 d1, d11, d2 - SND_DEVICE enums
1666 a1, a2 - corresponding ANDROID device enums
1667 B1, B2 - backend strings
1668
1669case 1
1670 uc->dev d1 (a1) B1
1671 new_uc->dev d1 (a1), d2 (a2) B1, B2
1672
1673 resolution: disable and enable uc->dev on d1
1674
1675case 2
1676 uc->dev d1 (a1) B1
1677 new_uc->dev d11 (a1) B1
1678
1679 resolution: need to switch uc since d1 and d11 are related
1680 (e.g. speaker and voice-speaker)
1681 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1682
1683case 3
1684 uc->dev d1 (a1) B1
1685 new_uc->dev d2 (a2) B2
1686
1687 resolution: no need to switch uc
1688
1689case 4
1690 uc->dev d1 (a1) B1
1691 new_uc->dev d2 (a2) B1
1692
1693 resolution: disable enable uc-dev on d2 since backends match
1694 we cannot enable two streams on two different devices if they
1695 share the same backend. e.g. if offload is on speaker device using
1696 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1697 using the same backend, offload must also be switched to voice-handset.
1698
1699case 5
1700 uc->dev d1 (a1) B1
1701 new_uc->dev d1 (a1), d2 (a2) B1
1702
1703 resolution: disable enable uc-dev on d2 since backends match
1704 we cannot enable two streams on two different devices if they
1705 share the same backend.
1706
1707case 6
1708 uc->dev d1 (a1) B1
1709 new_uc->dev d2 (a1) B2
1710
1711 resolution: no need to switch
1712
1713case 7
1714 uc->dev d1 (a1), d2 (a2) B1, B2
1715 new_uc->dev d1 (a1) B1
1716
1717 resolution: no need to switch
1718
Zhou Song4ba65882018-07-09 14:48:07 +08001719case 8
1720 uc->dev d1 (a1) B1
1721 new_uc->dev d11 (a1), d2 (a2) B1, B2
1722 resolution: compared to case 1, for this case, d1 and d11 are related
1723 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301724
1725case 9
1726 uc->dev d1 (a1), d2(a2) B1 B2
1727 new_uc->dev d1 (a1), d22 (a2) B1, B2
1728 resolution: disable enable uc-dev on d2 since backends match
1729 we cannot enable two streams on two different devices if they
1730 share the same backend. This is special case for combo use case
1731 with a2dp and sco devices which uses same backend.
1732 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001733*/
1734static snd_device_t derive_playback_snd_device(void * platform,
1735 struct audio_usecase *uc,
1736 struct audio_usecase *new_uc,
1737 snd_device_t new_snd_device)
1738{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001739 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001740
1741 snd_device_t d1 = uc->out_snd_device;
1742 snd_device_t d2 = new_snd_device;
1743
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001744 list_init(&a1);
1745 list_init(&a2);
1746
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301747 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301748 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001749 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1750 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301751 break;
1752 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001753 assign_devices(&a1, &uc->stream.out->device_list);
1754 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301755 break;
1756 }
1757
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001758 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001759 if (!compare_devices(&a1, &a2) &&
1760 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001761 snd_device_t d3[2];
1762 int num_devices = 0;
1763 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001764 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001765 &num_devices,
1766 d3);
1767 if (ret < 0) {
1768 if (ret != -ENOSYS) {
1769 ALOGW("%s failed to split snd_device %d",
1770 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001771 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001772 }
1773 goto end;
1774 }
1775
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001776 if (platform_check_backends_match(d3[0], d3[1])) {
1777 return d2; // case 5
1778 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301779 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1780 platform_check_backends_match(d1, d2))
1781 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001782 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301783 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001784 // check if d1 is related to any of d3's
1785 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001786 return d1; // case 1
1787 else
1788 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001789 }
1790 } else {
1791 if (platform_check_backends_match(d1, d2)) {
1792 return d2; // case 2, 4
1793 } else {
1794 return d1; // case 6, 3
1795 }
1796 }
1797
1798end:
1799 return d2; // return whatever was calculated before.
1800}
1801
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301803 struct audio_usecase *uc_info,
1804 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001805{
1806 struct listnode *node;
1807 struct audio_usecase *usecase;
1808 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301809 snd_device_t uc_derive_snd_device;
1810 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001811 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1812 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001813 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301814 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815 /*
1816 * This function is to make sure that all the usecases that are active on
1817 * the hardware codec backend are always routed to any one device that is
1818 * handled by the hardware codec.
1819 * For example, if low-latency and deep-buffer usecases are currently active
1820 * on speaker and out_set_parameters(headset) is received on low-latency
1821 * output, then we have to make sure deep-buffer is also switched to headset,
1822 * because of the limitation that both the devices cannot be enabled
1823 * at the same time as they share the same backend.
1824 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001825 /*
1826 * This call is to check if we need to force routing for a particular stream
1827 * If there is a backend configuration change for the device when a
1828 * new stream starts, then ADM needs to be closed and re-opened with the new
1829 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001830 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001831 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001832 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1833 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301834 /* For a2dp device reconfigure all active sessions
1835 * with new AFE encoder format based on a2dp state
1836 */
1837 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301838 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1839 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301840 audio_extn_a2dp_is_force_device_switch()) {
1841 force_routing = true;
1842 force_restart_session = true;
1843 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001844
1845 /*
1846 * Island cfg and power mode config needs to set before AFE port start.
1847 * Set force routing in case of voice device was enable before.
1848 */
1849 if (uc_info->type == VOICE_CALL &&
1850 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001851 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001852 platform_check_and_update_island_power_status(adev->platform,
1853 uc_info,
1854 snd_device)) {
1855 force_routing = true;
1856 ALOGD("%s:becf: force routing %d for power mode supported device",
1857 __func__, force_routing);
1858 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301859 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001862 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001863 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001864 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1865 switch_device[i] = false;
1866
1867 list_for_each(node, &adev->usecase_list) {
1868 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001869
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301870 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1871 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301872 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301873 platform_get_snd_device_name(usecase->out_snd_device),
1874 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301875 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1876 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301877 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1878 usecase, uc_info, snd_device);
1879 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001880 (is_codec_backend_out_device_type(&usecase->device_list) ||
1881 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1882 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1883 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1884 is_a2dp_out_device_type(&usecase->device_list) ||
1885 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301886 ((force_restart_session) ||
1887 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301888 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1889 __func__, use_case_table[usecase->id],
1890 platform_get_snd_device_name(usecase->out_snd_device));
1891 disable_audio_route(adev, usecase);
1892 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301893 /* Enable existing usecase on derived playback device */
1894 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301895 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301896 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001897 }
1898 }
1899
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301900 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1901 num_uc_to_switch);
1902
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001904 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301906 /* Make sure the previous devices to be disabled first and then enable the
1907 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001908 list_for_each(node, &adev->usecase_list) {
1909 usecase = node_to_item(node, struct audio_usecase, list);
1910 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001911 /* Check if output sound device to be switched can be split and if any
1912 of the split devices match with derived sound device */
1913 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1914 &num_devices, split_snd_devices) == 0) {
1915 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1916 for (i = 0; i < num_devices; i++) {
1917 /* Disable devices that do not match with derived sound device */
1918 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1919 disable_snd_device(adev, split_snd_devices[i]);
1920 }
1921 } else {
1922 disable_snd_device(adev, usecase->out_snd_device);
1923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 }
1925 }
1926
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001927 list_for_each(node, &adev->usecase_list) {
1928 usecase = node_to_item(node, struct audio_usecase, list);
1929 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001930 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1931 &num_devices, split_snd_devices) == 0) {
1932 /* Enable derived sound device only if it does not match with
1933 one of the split sound devices. This is because the matching
1934 sound device was not disabled */
1935 bool should_enable = true;
1936 for (i = 0; i < num_devices; i++) {
1937 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1938 should_enable = false;
1939 break;
1940 }
1941 }
1942 if (should_enable)
1943 enable_snd_device(adev, derive_snd_device[usecase->id]);
1944 } else {
1945 enable_snd_device(adev, derive_snd_device[usecase->id]);
1946 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001947 }
1948 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001950 /* Re-route all the usecases on the shared backend other than the
1951 specified usecase to new snd devices */
1952 list_for_each(node, &adev->usecase_list) {
1953 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301954 /* Update the out_snd_device only before enabling the audio route */
1955 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301956 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301957 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1958 use_case_table[usecase->id],
1959 platform_get_snd_device_name(usecase->out_snd_device));
1960 /* Update voc calibration before enabling Voice/VoIP route */
1961 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1962 status = platform_switch_voice_call_device_post(adev->platform,
1963 usecase->out_snd_device,
1964 platform_get_input_snd_device(
1965 adev->platform, NULL,
1966 &uc_info->device_list,
1967 usecase->type));
1968 enable_audio_route(adev, usecase);
1969 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1970 out_set_voip_volume(&usecase->stream.out->stream,
1971 usecase->stream.out->volume_l,
1972 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301973 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001974 }
1975 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976 }
1977}
1978
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301979static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001980 struct audio_usecase *uc_info,
1981 snd_device_t snd_device)
1982{
1983 struct listnode *node;
1984 struct audio_usecase *usecase;
1985 bool switch_device[AUDIO_USECASE_MAX];
1986 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001987 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001988 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001989
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301990 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1991 snd_device);
1992 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301993
1994 /*
1995 * Make sure out devices is checked against out codec backend device and
1996 * also in devices against in codec backend. Checking out device against in
1997 * codec backend or vice versa causes issues.
1998 */
1999 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002000 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002001
2002 /*
2003 * Island cfg and power mode config needs to set before AFE port start.
2004 * Set force routing in case of voice device was enable before.
2005 */
2006
2007 if (uc_info->type == VOICE_CALL &&
2008 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002009 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002010 platform_check_and_update_island_power_status(adev->platform,
2011 uc_info,
2012 snd_device)) {
2013 force_routing = true;
2014 ALOGD("%s:becf: force routing %d for power mode supported device",
2015 __func__, force_routing);
2016 }
2017
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002018 /*
2019 * This function is to make sure that all the active capture usecases
2020 * are always routed to the same input sound device.
2021 * For example, if audio-record and voice-call usecases are currently
2022 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2023 * is received for voice call then we have to make sure that audio-record
2024 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2025 * because of the limitation that two devices cannot be enabled
2026 * at the same time if they share the same backend.
2027 */
2028 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2029 switch_device[i] = false;
2030
2031 list_for_each(node, &adev->usecase_list) {
2032 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302033 /*
2034 * TODO: Enhance below condition to handle BT sco/USB multi recording
2035 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302036
2037 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2038 (usecase->in_snd_device != snd_device || force_routing));
2039 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2040 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2041 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002042 ((backend_check_cond &&
2043 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002044 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002045 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002046 is_single_device_type_equal(&usecase->device_list,
2047 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002048 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002049 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002050 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302051 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002052 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002053 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002054 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002055 switch_device[usecase->id] = true;
2056 num_uc_to_switch++;
2057 }
2058 }
2059
2060 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002061 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002062
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302063 /* Make sure the previous devices to be disabled first and then enable the
2064 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002065 list_for_each(node, &adev->usecase_list) {
2066 usecase = node_to_item(node, struct audio_usecase, list);
2067 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002068 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002069 }
2070 }
2071
2072 list_for_each(node, &adev->usecase_list) {
2073 usecase = node_to_item(node, struct audio_usecase, list);
2074 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002075 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002076 }
2077 }
2078
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002079 /* Re-route all the usecases on the shared backend other than the
2080 specified usecase to new snd devices */
2081 list_for_each(node, &adev->usecase_list) {
2082 usecase = node_to_item(node, struct audio_usecase, list);
2083 /* Update the in_snd_device only before enabling the audio route */
2084 if (switch_device[usecase->id] ) {
2085 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302086 /* Update voc calibration before enabling Voice/VoIP route */
2087 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2088 snd_device_t voip_snd_device;
2089 voip_snd_device = platform_get_output_snd_device(adev->platform,
2090 usecase->stream.out,
2091 usecase->type);
2092 status = platform_switch_voice_call_device_post(adev->platform,
2093 voip_snd_device,
2094 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002095 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302096 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002097 }
2098 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002099 }
2100}
2101
Mingming Yin3a941d42016-02-17 18:08:05 -08002102static void reset_hdmi_sink_caps(struct stream_out *out) {
2103 int i = 0;
2104
2105 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2106 out->supported_channel_masks[i] = 0;
2107 }
2108 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2109 out->supported_formats[i] = 0;
2110 }
2111 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2112 out->supported_sample_rates[i] = 0;
2113 }
2114}
2115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002117static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118{
Mingming Yin3a941d42016-02-17 18:08:05 -08002119 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002120 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2121 out->extconn.cs.controller,
2122 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Mingming Yin3a941d42016-02-17 18:08:05 -08002124 reset_hdmi_sink_caps(out);
2125
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002126 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002127 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002128 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002129 out->extconn.cs.stream);
2130 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002131 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002132 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002133 }
2134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002137 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002138 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002139 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2140 case 6:
2141 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2142 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2143 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2144 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2145 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2146 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 break;
2148 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002149 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002150 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 break;
2152 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002153
2154 // check channel format caps
2155 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002156 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2157 out->extconn.cs.controller,
2158 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002159 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2160 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2161 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2162 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2163 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2164 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2165 }
2166
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002167 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2168 out->extconn.cs.controller,
2169 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002170 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2171 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2172 }
2173
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002174 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2175 out->extconn.cs.controller,
2176 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002177 ALOGV(":%s HDMI supports DTS format", __func__);
2178 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2179 }
2180
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002181 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2182 out->extconn.cs.controller,
2183 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002184 ALOGV(":%s HDMI supports DTS HD format", __func__);
2185 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2186 }
2187
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002188 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2189 out->extconn.cs.controller,
2190 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002191 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2192 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2193 }
2194
Mingming Yin3a941d42016-02-17 18:08:05 -08002195
2196 // check sample rate caps
2197 i = 0;
2198 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002199 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2200 out->extconn.cs.controller,
2201 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002202 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2203 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2204 }
2205 }
2206
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002207 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208}
2209
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002210static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2211 uint32_t *supported_sample_rates __unused,
2212 uint32_t max_rates __unused)
2213{
2214 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2215 supported_sample_rates,
2216 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302217 ssize_t i = 0;
2218
2219 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002220 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2221 supported_sample_rates[i]);
2222 }
2223 return count;
2224}
2225
2226static inline int read_usb_sup_channel_masks(bool is_playback,
2227 audio_channel_mask_t *supported_channel_masks,
2228 uint32_t max_masks)
2229{
2230 int channels = audio_extn_usb_get_max_channels(is_playback);
2231 int channel_count;
2232 uint32_t num_masks = 0;
2233 if (channels > MAX_HIFI_CHANNEL_COUNT)
2234 channels = MAX_HIFI_CHANNEL_COUNT;
2235
2236 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002237 // start from 2 channels as framework currently doesn't support mono.
2238 if (channels >= FCC_2) {
2239 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2240 }
2241 for (channel_count = FCC_2;
2242 channel_count <= channels && num_masks < max_masks;
2243 ++channel_count) {
2244 supported_channel_masks[num_masks++] =
2245 audio_channel_mask_for_index_assignment_from_count(channel_count);
2246 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002247 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002248 // For capture we report all supported channel masks from 1 channel up.
2249 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002250 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2251 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002252 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2253 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2254 if (channel_count <= FCC_2) {
2255 mask = audio_channel_in_mask_from_count(channel_count);
2256 supported_channel_masks[num_masks++] = mask;
2257 }
2258 const audio_channel_mask_t index_mask =
2259 audio_channel_mask_for_index_assignment_from_count(channel_count);
2260 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2261 supported_channel_masks[num_masks++] = index_mask;
2262 }
2263 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002264 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302265
vincenttewf51c94e2019-05-07 10:28:53 +08002266 for (size_t i = 0; i < num_masks; ++i) {
2267 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2268 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302269 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002270 return num_masks;
2271}
2272
2273static inline int read_usb_sup_formats(bool is_playback __unused,
2274 audio_format_t *supported_formats,
2275 uint32_t max_formats __unused)
2276{
2277 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2278 switch (bitwidth) {
2279 case 24:
2280 // XXX : usb.c returns 24 for s24 and s24_le?
2281 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2282 break;
2283 case 32:
2284 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2285 break;
2286 case 16:
2287 default :
2288 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2289 break;
2290 }
2291 ALOGV("%s: %s supported format %d", __func__,
2292 is_playback ? "P" : "C", bitwidth);
2293 return 1;
2294}
2295
2296static inline int read_usb_sup_params_and_compare(bool is_playback,
2297 audio_format_t *format,
2298 audio_format_t *supported_formats,
2299 uint32_t max_formats,
2300 audio_channel_mask_t *mask,
2301 audio_channel_mask_t *supported_channel_masks,
2302 uint32_t max_masks,
2303 uint32_t *rate,
2304 uint32_t *supported_sample_rates,
2305 uint32_t max_rates) {
2306 int ret = 0;
2307 int num_formats;
2308 int num_masks;
2309 int num_rates;
2310 int i;
2311
2312 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2313 max_formats);
2314 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2315 max_masks);
2316
2317 num_rates = read_usb_sup_sample_rates(is_playback,
2318 supported_sample_rates, max_rates);
2319
2320#define LUT(table, len, what, dflt) \
2321 for (i=0; i<len && (table[i] != what); i++); \
2322 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2323
2324 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2325 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2326 LUT(supported_sample_rates, num_rates, *rate, 0);
2327
2328#undef LUT
2329 return ret < 0 ? -EINVAL : 0; // HACK TBD
2330}
2331
Alexy Josephb1379942016-01-29 15:49:38 -08002332audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002333 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002334{
2335 struct audio_usecase *usecase;
2336 struct listnode *node;
2337
2338 list_for_each(node, &adev->usecase_list) {
2339 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002340 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002341 ALOGV("%s: usecase id %d", __func__, usecase->id);
2342 return usecase->id;
2343 }
2344 }
2345 return USECASE_INVALID;
2346}
2347
Alexy Josephb1379942016-01-29 15:49:38 -08002348struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002349 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002350{
2351 struct audio_usecase *usecase;
2352 struct listnode *node;
2353
2354 list_for_each(node, &adev->usecase_list) {
2355 usecase = node_to_item(node, struct audio_usecase, list);
2356 if (usecase->id == uc_id)
2357 return usecase;
2358 }
2359 return NULL;
2360}
2361
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302362/*
2363 * is a true native playback active
2364 */
2365bool audio_is_true_native_stream_active(struct audio_device *adev)
2366{
2367 bool active = false;
2368 int i = 0;
2369 struct listnode *node;
2370
2371 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2372 ALOGV("%s:napb: not in true mode or non hdphones device",
2373 __func__);
2374 active = false;
2375 goto exit;
2376 }
2377
2378 list_for_each(node, &adev->usecase_list) {
2379 struct audio_usecase *uc;
2380 uc = node_to_item(node, struct audio_usecase, list);
2381 struct stream_out *curr_out =
2382 (struct stream_out*) uc->stream.out;
2383
2384 if (curr_out && PCM_PLAYBACK == uc->type) {
2385 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2386 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2387 uc->id, curr_out->sample_rate,
2388 curr_out->bit_width,
2389 platform_get_snd_device_name(uc->out_snd_device));
2390
2391 if (is_offload_usecase(uc->id) &&
2392 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2393 active = true;
2394 ALOGD("%s:napb:native stream detected", __func__);
2395 }
2396 }
2397 }
2398exit:
2399 return active;
2400}
2401
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002402uint32_t adev_get_dsp_bit_width_enforce_mode()
2403{
2404 if (adev == NULL) {
2405 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2406 return 0;
2407 }
2408 return adev->dsp_bit_width_enforce_mode;
2409}
2410
2411static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2412{
2413 char value[PROPERTY_VALUE_MAX];
2414 int trial;
2415 uint32_t dsp_bit_width_enforce_mode = 0;
2416
2417 if (!mixer) {
2418 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2419 __func__);
2420 return 0;
2421 }
2422
2423 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2424 value, NULL) > 0) {
2425 trial = atoi(value);
2426 switch (trial) {
2427 case 16:
2428 dsp_bit_width_enforce_mode = 16;
2429 break;
2430 case 24:
2431 dsp_bit_width_enforce_mode = 24;
2432 break;
2433 case 32:
2434 dsp_bit_width_enforce_mode = 32;
2435 break;
2436 default:
2437 dsp_bit_width_enforce_mode = 0;
2438 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2439 break;
2440 }
2441 }
2442
2443 return dsp_bit_width_enforce_mode;
2444}
2445
2446static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2447 uint32_t enforce_mode,
2448 bool enable)
2449{
2450 struct mixer_ctl *ctl = NULL;
2451 const char *mixer_ctl_name = "ASM Bit Width";
2452 uint32_t asm_bit_width_mode = 0;
2453
2454 if (enforce_mode == 0) {
2455 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2456 return;
2457 }
2458
2459 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2460 if (!ctl) {
2461 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2462 __func__, mixer_ctl_name);
2463 return;
2464 }
2465
2466 if (enable)
2467 asm_bit_width_mode = enforce_mode;
2468 else
2469 asm_bit_width_mode = 0;
2470
2471 ALOGV("%s DSP bit width feature status is %d width=%d",
2472 __func__, enable, asm_bit_width_mode);
2473 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2474 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2475 asm_bit_width_mode);
2476
2477 return;
2478}
2479
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302480/*
2481 * if native DSD playback active
2482 */
2483bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2484{
2485 bool active = false;
2486 struct listnode *node = NULL;
2487 struct audio_usecase *uc = NULL;
2488 struct stream_out *curr_out = NULL;
2489
2490 list_for_each(node, &adev->usecase_list) {
2491 uc = node_to_item(node, struct audio_usecase, list);
2492 curr_out = (struct stream_out*) uc->stream.out;
2493
2494 if (curr_out && PCM_PLAYBACK == uc->type &&
2495 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2496 active = true;
2497 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302498 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302499 }
2500 }
2501 return active;
2502}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302503
2504static bool force_device_switch(struct audio_usecase *usecase)
2505{
2506 bool ret = false;
2507 bool is_it_true_mode = false;
2508
Zhou Song30f2c3e2018-02-08 14:02:15 +08002509 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302510 usecase->type == TRANSCODE_LOOPBACK_RX ||
2511 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002512 return false;
2513 }
2514
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002515 if(usecase->stream.out == NULL) {
2516 ALOGE("%s: stream.out is NULL", __func__);
2517 return false;
2518 }
2519
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302520 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002521 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002522 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2523 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302524 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2525 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2526 (!is_it_true_mode && adev->native_playback_enabled)){
2527 ret = true;
2528 ALOGD("napb: time to toggle native mode");
2529 }
2530 }
2531
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302532 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302533 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2534 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002535 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302536 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302537 ALOGD("Force a2dp device switch to update new encoder config");
2538 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002539 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302540
Florian Pfister1a84f312018-07-19 14:38:18 +02002541 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302542 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2543 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002544 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302545 return ret;
2546}
2547
Aalique Grahame22e49102018-12-18 14:23:57 -08002548static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2549{
2550 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2551}
2552
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302553bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2554{
2555 bool ret=false;
2556 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002557 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2558 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302559 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2560 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002561 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302562 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002563 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2564 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302565 ret = true;
2566
2567 return ret;
2568}
2569
2570bool is_a2dp_device(snd_device_t out_snd_device)
2571{
2572 bool ret=false;
2573 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2574 ret = true;
2575
2576 return ret;
2577}
2578
2579bool is_bt_soc_on(struct audio_device *adev)
2580{
2581 struct mixer_ctl *ctl;
2582 char *mixer_ctl_name = "BT SOC status";
2583 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2584 bool bt_soc_status = true;
2585 if (!ctl) {
2586 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2587 __func__, mixer_ctl_name);
2588 /*This is to ensure we dont break targets which dont have the kernel change*/
2589 return true;
2590 }
2591 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2592 ALOGD("BT SOC status: %d",bt_soc_status);
2593 return bt_soc_status;
2594}
2595
Zhou Song331c8e52019-08-26 14:16:12 +08002596static int configure_btsco_sample_rate(snd_device_t snd_device)
2597{
2598 struct mixer_ctl *ctl = NULL;
2599 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2600 char *rate_str = NULL;
2601 bool is_rx_dev = true;
2602
2603 if (is_btsco_device(snd_device, snd_device)) {
2604 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2605 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2606 if (!ctl_sr_tx || !ctl_sr_rx) {
2607 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2608 if (!ctl_sr)
2609 return -ENOSYS;
2610 }
2611
2612 switch (snd_device) {
2613 case SND_DEVICE_OUT_BT_SCO:
2614 rate_str = "KHZ_8";
2615 break;
2616 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2617 case SND_DEVICE_IN_BT_SCO_MIC:
2618 rate_str = "KHZ_8";
2619 is_rx_dev = false;
2620 break;
2621 case SND_DEVICE_OUT_BT_SCO_WB:
2622 rate_str = "KHZ_16";
2623 break;
2624 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2625 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2626 rate_str = "KHZ_16";
2627 is_rx_dev = false;
2628 break;
2629 default:
2630 return 0;
2631 }
2632
2633 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2634 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2635 return -ENOSYS;
2636 }
2637 return 0;
2638}
2639
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302640int out_standby_l(struct audio_stream *stream);
2641
Eric Laurent637e2d42018-11-15 12:24:31 -08002642struct stream_in *adev_get_active_input(const struct audio_device *adev)
2643{
2644 struct listnode *node;
2645 struct stream_in *last_active_in = NULL;
2646
2647 /* Get last added active input.
2648 * TODO: We may use a priority mechanism to pick highest priority active source */
2649 list_for_each(node, &adev->usecase_list)
2650 {
2651 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2652 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2653 last_active_in = usecase->stream.in;
2654 }
2655
2656 return last_active_in;
2657}
2658
2659struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2660{
2661 struct listnode *node;
2662
2663 /* First check active inputs with voice communication source and then
2664 * any input if audio mode is in communication */
2665 list_for_each(node, &adev->usecase_list)
2666 {
2667 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2668 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2669 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2670 return usecase->stream.in;
2671 }
2672 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2673 return adev_get_active_input(adev);
2674
2675 return NULL;
2676}
2677
Carter Hsu2e429db2019-05-14 18:50:52 +08002678/*
2679 * Aligned with policy.h
2680 */
2681static inline int source_priority(int inputSource)
2682{
2683 switch (inputSource) {
2684 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2685 return 9;
2686 case AUDIO_SOURCE_CAMCORDER:
2687 return 8;
2688 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2689 return 7;
2690 case AUDIO_SOURCE_UNPROCESSED:
2691 return 6;
2692 case AUDIO_SOURCE_MIC:
2693 return 5;
2694 case AUDIO_SOURCE_ECHO_REFERENCE:
2695 return 4;
2696 case AUDIO_SOURCE_FM_TUNER:
2697 return 3;
2698 case AUDIO_SOURCE_VOICE_RECOGNITION:
2699 return 2;
2700 case AUDIO_SOURCE_HOTWORD:
2701 return 1;
2702 default:
2703 break;
2704 }
2705 return 0;
2706}
2707
2708static struct stream_in *get_priority_input(struct audio_device *adev)
2709{
2710 struct listnode *node;
2711 struct audio_usecase *usecase;
2712 int last_priority = 0, priority;
2713 struct stream_in *priority_in = NULL;
2714 struct stream_in *in;
2715
2716 list_for_each(node, &adev->usecase_list) {
2717 usecase = node_to_item(node, struct audio_usecase, list);
2718 if (usecase->type == PCM_CAPTURE) {
2719 in = usecase->stream.in;
2720 if (!in)
2721 continue;
2722 priority = source_priority(in->source);
2723
2724 if (priority > last_priority) {
2725 last_priority = priority;
2726 priority_in = in;
2727 }
2728 }
2729 }
2730 return priority_in;
2731}
2732
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002733int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002735 snd_device_t out_snd_device = SND_DEVICE_NONE;
2736 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 struct audio_usecase *usecase = NULL;
2738 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002739 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002740 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302741 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002742 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002743 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302745 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2746
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002747 usecase = get_usecase_from_list(adev, uc_id);
2748 if (usecase == NULL) {
2749 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2750 return -EINVAL;
2751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002753 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002754 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002755 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002756 (usecase->type == ICC_CALL) ||
2757 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302758 if(usecase->stream.out == NULL) {
2759 ALOGE("%s: stream.out is NULL", __func__);
2760 return -EINVAL;
2761 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002762 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002763 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2764 uc_id);
2765 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2766 uc_id);
2767 } else {
2768 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302769 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002770 in_snd_device = platform_get_input_snd_device(adev->platform,
2771 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 &usecase->stream.out->device_list,
2773 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002774 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002775 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302776 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302777 if (usecase->stream.inout == NULL) {
2778 ALOGE("%s: stream.inout is NULL", __func__);
2779 return -EINVAL;
2780 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002781 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302782 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2783 stream_out.format = usecase->stream.inout->out_config.format;
2784 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302785 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002786 assign_devices(&usecase->device_list,
2787 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302788 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2789 if (usecase->stream.inout == NULL) {
2790 ALOGE("%s: stream.inout is NULL", __func__);
2791 return -EINVAL;
2792 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302793 struct listnode out_devices;
2794 list_init(&out_devices);
2795 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2796 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002797 assign_devices(&usecase->device_list,
2798 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002799 } else {
2800 /*
2801 * If the voice call is active, use the sound devices of voice call usecase
2802 * so that it would not result any device switch. All the usecases will
2803 * be switched to new device when select_devices() is called for voice call
2804 * usecase. This is to avoid switching devices for voice call when
2805 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002806 * choose voice call device only if the use case device is
2807 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002808 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002809 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002810 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002811 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002812 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2813 is_codec_backend_out_device_type(&usecase->device_list)) ||
2814 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2815 is_codec_backend_in_device_type(&usecase->device_list)) ||
2816 is_single_device_type_equal(&vc_usecase->device_list,
2817 AUDIO_DEVICE_OUT_HEARING_AID) ||
2818 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002819 AUDIO_DEVICE_IN_VOICE_CALL) ||
2820 (is_single_device_type_equal(&usecase->device_list,
2821 AUDIO_DEVICE_IN_USB_HEADSET) &&
2822 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302823 AUDIO_DEVICE_OUT_USB_HEADSET))||
2824 (is_single_device_type_equal(&usecase->device_list,
2825 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2826 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002827 in_snd_device = vc_usecase->in_snd_device;
2828 out_snd_device = vc_usecase->out_snd_device;
2829 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002830 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002831 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002832 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002833 if ((voip_usecase != NULL) &&
2834 (usecase->type == PCM_PLAYBACK) &&
2835 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002836 out_snd_device_backend_match = platform_check_backends_match(
2837 voip_usecase->out_snd_device,
2838 platform_get_output_snd_device(
2839 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302840 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002841 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002842 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2843 (is_codec_backend_out_device_type(&usecase->device_list) ||
2844 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002845 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002846 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002847 in_snd_device = voip_usecase->in_snd_device;
2848 out_snd_device = voip_usecase->out_snd_device;
2849 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002850 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002851 hfp_ucid = audio_extn_hfp_get_usecase();
2852 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002853 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002854 in_snd_device = hfp_usecase->in_snd_device;
2855 out_snd_device = hfp_usecase->out_snd_device;
2856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002857 }
2858 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302859 if (usecase->stream.out == NULL) {
2860 ALOGE("%s: stream.out is NULL", __func__);
2861 return -EINVAL;
2862 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002863 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002864 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002865 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002866 struct stream_out *voip_out = adev->primary_output;
2867 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002868 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002869 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2870 else
2871 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302872 usecase->stream.out,
2873 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002874 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002875
Eric Laurent637e2d42018-11-15 12:24:31 -08002876 if (voip_usecase)
2877 voip_out = voip_usecase->stream.out;
2878
2879 if (usecase->stream.out == voip_out && voip_in != NULL)
2880 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002882 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302883 if (usecase->stream.in == NULL) {
2884 ALOGE("%s: stream.in is NULL", __func__);
2885 return -EINVAL;
2886 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002887 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002888 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002889 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002890 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002891 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002892 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002893
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002894 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002895 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002896 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2897 USECASE_AUDIO_PLAYBACK_VOIP);
2898
Carter Hsu2e429db2019-05-14 18:50:52 +08002899 usecase->stream.in->enable_ec_port = false;
2900
Zhou Song62ea0282020-03-22 19:53:01 +08002901 bool is_ha_usecase = adev->ha_proxy_enable ?
2902 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2903 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2904 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002905 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002906 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002907 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002908 } else if (adev->primary_output &&
2909 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002910 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002911 } else {
2912 /* forcing speaker o/p device to get matching i/p pair
2913 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002914 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002915 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002916 priority_in = voip_in;
2917 } else {
2918 /* get the input with the highest priority source*/
2919 priority_in = get_priority_input(adev);
2920
Susan Wang727dd6b2021-03-26 11:28:59 -04002921 if (!priority_in ||
2922 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08002923 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002924 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002925 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2926 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2927 }
2928 else
2929 in_snd_device = platform_get_input_snd_device(adev->platform,
2930 priority_in,
2931 &out_devices,
2932 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002933 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002934 }
2935 }
2936
2937 if (out_snd_device == usecase->out_snd_device &&
2938 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302939
2940 if (!force_device_switch(usecase))
2941 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002944 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002945 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002946 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002947 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2948 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302949 }
2950
Aalique Grahame22e49102018-12-18 14:23:57 -08002951 if (out_snd_device != SND_DEVICE_NONE &&
2952 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2953 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2954 __func__,
2955 use_case_table[uc_id],
2956 adev->last_logged_snd_device[uc_id][0],
2957 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2958 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2959 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2960 -1,
2961 out_snd_device,
2962 platform_get_snd_device_name(out_snd_device),
2963 platform_get_snd_device_acdb_id(out_snd_device));
2964 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2965 }
2966 if (in_snd_device != SND_DEVICE_NONE &&
2967 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2968 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2969 __func__,
2970 use_case_table[uc_id],
2971 adev->last_logged_snd_device[uc_id][1],
2972 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2973 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2974 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2975 -1,
2976 in_snd_device,
2977 platform_get_snd_device_name(in_snd_device),
2978 platform_get_snd_device_acdb_id(in_snd_device));
2979 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2980 }
2981
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 /*
2984 * Limitation: While in call, to do a device switch we need to disable
2985 * and enable both RX and TX devices though one of them is same as current
2986 * device.
2987 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002988 if ((usecase->type == VOICE_CALL) &&
2989 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2990 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002991 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002992 }
2993
2994 if (((usecase->type == VOICE_CALL) ||
2995 (usecase->type == VOIP_CALL)) &&
2996 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2997 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302998 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002999 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003000 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003001
3002 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303003 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003004 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003005 }
3006
Aalique Grahame22e49102018-12-18 14:23:57 -08003007 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3008 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003009 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303010 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003011 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3012 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3013 else
3014 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303015 }
3016
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003017 /* Disable current sound devices */
3018 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003019 disable_audio_route(adev, usecase);
3020 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 }
3022
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003023 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003024 disable_audio_route(adev, usecase);
3025 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 }
3027
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003028 /* Applicable only on the targets that has external modem.
3029 * New device information should be sent to modem before enabling
3030 * the devices to reduce in-call device switch time.
3031 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003032 if ((usecase->type == VOICE_CALL) &&
3033 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3034 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003035 status = platform_switch_voice_call_enable_device_config(adev->platform,
3036 out_snd_device,
3037 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003038 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003039
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003040 /* Enable new sound devices */
3041 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003042 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303043 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303044 if (platform_check_codec_asrc_support(adev->platform))
3045 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003046 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003047 /* Enable haptics device for haptic usecase */
3048 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3049 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 }
3051
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003052 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303053 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003054 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003055 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003056
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303057 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003058 status = platform_switch_voice_call_device_post(adev->platform,
3059 out_snd_device,
3060 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003061
sangwoo170731f2013-06-08 15:36:36 +09003062 usecase->in_snd_device = in_snd_device;
3063 usecase->out_snd_device = out_snd_device;
3064
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303065 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3066 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303067 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003068 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003069 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003070 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3071 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3072 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3073 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3074 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3075 /*
3076 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3077 * configured device sample rate, if not update the COPP rate to be equal to the
3078 * device sample rate, else open COPP at stream sample rate
3079 */
3080 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3081 usecase->stream.out->sample_rate,
3082 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303083 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303084 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3085 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303086 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003087 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3088 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3089 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3090 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003091 }
3092 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003093
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303094 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3095 struct stream_in *voip_in = get_voice_communication_input(adev);
3096 struct audio_usecase *voip_in_usecase = NULL;
3097 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3098 if (voip_in != NULL &&
3099 voip_in_usecase != NULL &&
3100 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3101 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3102 (voip_in_usecase->in_snd_device ==
3103 platform_get_input_snd_device(adev->platform, voip_in,
3104 &usecase->stream.out->device_list,usecase->type))) {
3105 /*
3106 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3107 * for enabling echo-reference-voip with correct port
3108 */
3109 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3110 disable_audio_route(adev, voip_in_usecase);
3111 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3112 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3113 enable_audio_route(adev, voip_in_usecase);
3114 }
3115 }
3116
3117
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003118 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003119
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003120 /* If input stream is already running then effect needs to be
3121 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003122 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003123 check_and_enable_effect(adev);
3124
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003125 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003126 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303127 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003128 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3129
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003130 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303131 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003132 voice_extn_compress_voip_is_started(adev))
3133 voice_set_sidetone(adev, out_snd_device, true);
3134 }
3135
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003136 /* Applicable only on the targets that has external modem.
3137 * Enable device command should be sent to modem only after
3138 * enabling voice call mixer controls
3139 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003140 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003141 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3142 out_snd_device,
3143 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303144
3145 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003146 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303147 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003148 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303149 if (is_bt_soc_on(adev) == false){
3150 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003151 if (in->pcm != NULL)
3152 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303153 }
3154 }
3155 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3156 && usecase->stream.out->started) {
3157 if (is_bt_soc_on(adev) == false) {
3158 ALOGD("BT SCO/A2DP disconnected while in connection");
3159 out_standby_l(&usecase->stream.out->stream.common);
3160 }
3161 }
3162 } else if ((usecase->stream.out != NULL) &&
3163 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303164 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3165 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003166 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303167 usecase->stream.out->started) {
3168 if (is_bt_soc_on(adev) == false) {
3169 ALOGD("BT SCO/A2dp disconnected while in connection");
3170 out_standby_l(&usecase->stream.out->stream.common);
3171 }
3172 }
3173 }
3174
Yung Ti Su70cb8242018-06-22 17:38:47 +08003175 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003176 struct stream_out *voip_out = voip_usecase->stream.out;
3177 audio_extn_utils_send_app_type_gain(adev,
3178 voip_out->app_type_cfg.app_type,
3179 &voip_out->app_type_cfg.gain[0]);
3180 }
3181
Ajender Reddyb940b832021-07-07 11:51:42 +05303182 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 return status;
3185}
3186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187static int stop_input_stream(struct stream_in *in)
3188{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303189 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303191
3192 if (in == NULL) {
3193 ALOGE("%s: stream_in ptr is NULL", __func__);
3194 return -EINVAL;
3195 }
3196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003198 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Eric Laurent994a6932013-07-17 11:51:42 -07003200 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 uc_info = get_usecase_from_list(adev, in->usecase);
3203 if (uc_info == NULL) {
3204 ALOGE("%s: Could not find the usecase (%d) in the list",
3205 __func__, in->usecase);
3206 return -EINVAL;
3207 }
3208
Carter Hsu2e429db2019-05-14 18:50:52 +08003209 priority_in = get_priority_input(adev);
3210
Derek Chenea197282019-01-07 17:35:01 -08003211 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3212 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003213
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003214 /* Close in-call recording streams */
3215 voice_check_and_stop_incall_rec_usecase(adev, in);
3216
Eric Laurent150dbfe2013-02-27 14:31:02 -08003217 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003218 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003219
3220 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003221 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003223 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303224 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3225
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003226 list_remove(&uc_info->list);
3227 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228
Carter Hsu2e429db2019-05-14 18:50:52 +08003229 if (priority_in == in) {
3230 priority_in = get_priority_input(adev);
3231 if (priority_in)
3232 select_devices(adev, priority_in->usecase);
3233 }
3234
Vatsal Buchac09ae062018-11-14 13:25:08 +05303235 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003236 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 return ret;
3238}
3239
3240int start_input_stream(struct stream_in *in)
3241{
3242 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003243 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303245
3246 if (in == NULL) {
3247 ALOGE("%s: stream_in ptr is NULL", __func__);
3248 return -EINVAL;
3249 }
3250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003252 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003253 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254
Mingming Yin2664a5b2015-09-03 10:53:11 -07003255 if (get_usecase_from_list(adev, usecase) == NULL)
3256 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303257 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3258 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003259
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303260 if (CARD_STATUS_OFFLINE == in->card_status||
3261 CARD_STATUS_OFFLINE == adev->card_status) {
3262 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303263 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303264 goto error_config;
3265 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303266
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003267 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303268 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303269 ALOGE("%s: SCO profile is not ready, return error", __func__);
3270 ret = -EIO;
3271 goto error_config;
3272 }
3273 }
3274
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003275 /* Check if source matches incall recording usecase criteria */
3276 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3277 if (ret)
3278 goto error_config;
3279 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003280 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3281
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303282 if (audio_extn_cin_attached_usecase(in))
3283 audio_extn_cin_acquire_usecase(in);
3284
Mingming Yin2664a5b2015-09-03 10:53:11 -07003285 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3286 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3287 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003288 ret = -EINVAL;
3289 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003290 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003291
Eric Laurentb23d5282013-05-14 15:27:20 -07003292 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 if (in->pcm_device_id < 0) {
3294 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3295 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003296 ret = -EINVAL;
3297 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003301
3302 if (!uc_info) {
3303 ret = -ENOMEM;
3304 goto error_config;
3305 }
3306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 uc_info->id = in->usecase;
3308 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003309 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003310 list_init(&uc_info->device_list);
3311 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003312 uc_info->in_snd_device = SND_DEVICE_NONE;
3313 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003315 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003316 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303317 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3318 adev->perf_lock_opts,
3319 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003320 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321
Derek Chenea197282019-01-07 17:35:01 -08003322 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3323 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003324
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303325 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3326
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303327 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303328 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303329 if (ret)
3330 goto error_open;
3331 else
3332 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003333 }
3334
Haynes Mathew George16081042017-05-31 17:16:49 -07003335 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003336 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003337 ALOGE("%s: pcm stream not ready", __func__);
3338 goto error_open;
3339 }
3340 ret = pcm_start(in->pcm);
3341 if (ret < 0) {
3342 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3343 goto error_open;
3344 }
3345 } else {
3346 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3347 unsigned int pcm_open_retry_count = 0;
3348
Zhou Song62ea0282020-03-22 19:53:01 +08003349 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3350 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003351 flags |= PCM_MMAP | PCM_NOIRQ;
3352 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3353 } else if (in->realtime) {
3354 flags |= PCM_MMAP | PCM_NOIRQ;
3355 }
3356
Garmond Leunge2433c32017-09-28 21:51:22 -07003357 if (audio_extn_ffv_get_stream() == in) {
3358 ALOGD("%s: ffv stream, update pcm config", __func__);
3359 audio_extn_ffv_update_pcm_config(&config);
3360 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003361 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3362 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3363
3364 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003365 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003366 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003367 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003368 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303369 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303370 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3371 adev->card_status = CARD_STATUS_OFFLINE;
3372 in->card_status = CARD_STATUS_OFFLINE;
3373 ret = -EIO;
3374 goto error_open;
3375 }
3376
Haynes Mathew George16081042017-05-31 17:16:49 -07003377 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3378 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3379 if (in->pcm != NULL) {
3380 pcm_close(in->pcm);
3381 in->pcm = NULL;
3382 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003383 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003384 ret = -EIO;
3385 goto error_open;
3386 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003387 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003388 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3389 continue;
3390 }
3391 break;
3392 }
3393
3394 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003395 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003396 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003397 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003398 if (ret < 0) {
3399 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3400 pcm_close(in->pcm);
3401 in->pcm = NULL;
3402 goto error_open;
3403 }
3404 register_in_stream(in);
3405 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003406 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003407 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003408 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003409 if (ret < 0) {
3410 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003411 pcm_close(in->pcm);
3412 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003413 goto error_open;
3414 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003415 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003416 }
3417
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003418 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003419 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3420 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003421
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003422 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303423 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3424
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303425done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003426 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303427 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303428 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303429 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003430 return ret;
3431
3432error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003433 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303434 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003436
Eric Laurentc8400632013-02-14 19:04:54 -08003437error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003438 if (audio_extn_cin_attached_usecase(in))
3439 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303440 /*
3441 * sleep 50ms to allow sufficient time for kernel
3442 * drivers to recover incases like SSR.
3443 */
3444 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003445 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303446 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003447 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448}
3449
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003450void lock_input_stream(struct stream_in *in)
3451{
3452 pthread_mutex_lock(&in->pre_lock);
3453 pthread_mutex_lock(&in->lock);
3454 pthread_mutex_unlock(&in->pre_lock);
3455}
3456
3457void lock_output_stream(struct stream_out *out)
3458{
3459 pthread_mutex_lock(&out->pre_lock);
3460 pthread_mutex_lock(&out->lock);
3461 pthread_mutex_unlock(&out->pre_lock);
3462}
3463
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464/* must be called with out->lock locked */
3465static int send_offload_cmd_l(struct stream_out* out, int command)
3466{
3467 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3468
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003469 if (!cmd) {
3470 ALOGE("failed to allocate mem for command 0x%x", command);
3471 return -ENOMEM;
3472 }
3473
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 ALOGVV("%s %d", __func__, command);
3475
3476 cmd->cmd = command;
3477 list_add_tail(&out->offload_cmd_list, &cmd->node);
3478 pthread_cond_signal(&out->offload_cond);
3479 return 0;
3480}
3481
Gautam Manam14c198b2020-12-24 14:08:04 +05303482/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483static void stop_compressed_output_l(struct stream_out *out)
3484{
Gautam Manam14c198b2020-12-24 14:08:04 +05303485 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303487 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003490 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003491 if (out->compr != NULL) {
3492 compress_stop(out->compr);
3493 while (out->offload_thread_blocked) {
3494 pthread_cond_wait(&out->cond, &out->lock);
3495 }
3496 }
3497}
3498
Varun Balaraje49253e2017-07-06 19:48:56 +05303499bool is_interactive_usecase(audio_usecase_t uc_id)
3500{
3501 unsigned int i;
3502 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3503 if (uc_id == interactive_usecases[i])
3504 return true;
3505 }
3506 return false;
3507}
3508
3509static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3510{
3511 audio_usecase_t ret_uc = USECASE_INVALID;
3512 unsigned int intract_uc_index;
3513 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3514
3515 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3516 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3517 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3518 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3519 ret_uc = interactive_usecases[intract_uc_index];
3520 break;
3521 }
3522 }
3523
3524 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3525 return ret_uc;
3526}
3527
3528static void free_interactive_usecase(struct audio_device *adev,
3529 audio_usecase_t uc_id)
3530{
3531 unsigned int interact_uc_index;
3532 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3533
3534 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3535 if (interactive_usecases[interact_uc_index] == uc_id) {
3536 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3537 break;
3538 }
3539 }
3540 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3541}
3542
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003543bool is_offload_usecase(audio_usecase_t uc_id)
3544{
3545 unsigned int i;
3546 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3547 if (uc_id == offload_usecases[i])
3548 return true;
3549 }
3550 return false;
3551}
3552
Dhananjay Kumarac341582017-02-23 23:42:25 +05303553static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003554{
vivek mehta446c3962015-09-14 10:57:35 -07003555 audio_usecase_t ret_uc = USECASE_INVALID;
3556 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003557 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003558 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303559 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003560 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3561 else
3562 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003563
vivek mehta446c3962015-09-14 10:57:35 -07003564 pthread_mutex_lock(&adev->lock);
3565 if (get_usecase_from_list(adev, ret_uc) != NULL)
3566 ret_uc = USECASE_INVALID;
3567 pthread_mutex_unlock(&adev->lock);
3568
3569 return ret_uc;
3570 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003571
3572 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003573 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3574 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3575 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3576 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003577 break;
3578 }
3579 }
vivek mehta446c3962015-09-14 10:57:35 -07003580
3581 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3582 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003583}
3584
3585static void free_offload_usecase(struct audio_device *adev,
3586 audio_usecase_t uc_id)
3587{
vivek mehta446c3962015-09-14 10:57:35 -07003588 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003589 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003590
3591 if (!adev->multi_offload_enable)
3592 return;
3593
3594 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3595 if (offload_usecases[offload_uc_index] == uc_id) {
3596 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003597 break;
3598 }
3599 }
3600 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3601}
3602
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603static void *offload_thread_loop(void *context)
3604{
3605 struct stream_out *out = (struct stream_out *) context;
3606 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003607 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003610 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3612
3613 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003614 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003615 out->offload_state = OFFLOAD_STATE_IDLE;
3616 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003617 for (;;) {
3618 struct offload_cmd *cmd = NULL;
3619 stream_callback_event_t event;
3620 bool send_callback = false;
3621
3622 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3623 __func__, list_empty(&out->offload_cmd_list),
3624 out->offload_state);
3625 if (list_empty(&out->offload_cmd_list)) {
3626 ALOGV("%s SLEEPING", __func__);
3627 pthread_cond_wait(&out->offload_cond, &out->lock);
3628 ALOGV("%s RUNNING", __func__);
3629 continue;
3630 }
3631
3632 item = list_head(&out->offload_cmd_list);
3633 cmd = node_to_item(item, struct offload_cmd, node);
3634 list_remove(item);
3635
3636 ALOGVV("%s STATE %d CMD %d out->compr %p",
3637 __func__, out->offload_state, cmd->cmd, out->compr);
3638
3639 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3640 free(cmd);
3641 break;
3642 }
3643
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003644 // allow OFFLOAD_CMD_ERROR reporting during standby
3645 // this is needed to handle failures during compress_open
3646 // Note however that on a pause timeout, the stream is closed
3647 // and no offload usecase will be active. Therefore this
3648 // special case is needed for compress_open failures alone
3649 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3650 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003652 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653 pthread_cond_signal(&out->cond);
3654 continue;
3655 }
3656 out->offload_thread_blocked = true;
3657 pthread_mutex_unlock(&out->lock);
3658 send_callback = false;
3659 switch(cmd->cmd) {
3660 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003661 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003663 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 send_callback = true;
3665 event = STREAM_CBK_EVENT_WRITE_READY;
3666 break;
3667 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003668 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303669 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003670 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303671 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003672 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303673 if (ret < 0)
3674 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303675 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303676 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003677 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003678 else
3679 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003680 if (-ENETRESET != ret && !(-EINTR == ret &&
3681 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303682 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303683 pthread_mutex_lock(&out->lock);
3684 out->send_new_metadata = 1;
3685 out->send_next_track_params = true;
3686 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303687 event = STREAM_CBK_EVENT_DRAIN_READY;
3688 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3689 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303690 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 break;
3692 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003693 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003694 ret = compress_drain(out->compr);
3695 ALOGD("copl(%p):out of compress_drain", out);
3696 // EINTR check avoids drain interruption due to SSR
3697 if (-ENETRESET != ret && !(-EINTR == ret &&
3698 CARD_STATUS_OFFLINE == out->card_status)) {
3699 send_callback = true;
3700 event = STREAM_CBK_EVENT_DRAIN_READY;
3701 } else
3702 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303704 case OFFLOAD_CMD_ERROR:
3705 ALOGD("copl(%p): sending error callback to AF", out);
3706 send_callback = true;
3707 event = STREAM_CBK_EVENT_ERROR;
3708 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003709 default:
3710 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3711 break;
3712 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003713 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003714 out->offload_thread_blocked = false;
3715 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003716 if (send_callback && out->client_callback) {
3717 ALOGVV("%s: sending client_callback event %d", __func__, event);
3718 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003719 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003720 free(cmd);
3721 }
3722
3723 pthread_cond_signal(&out->cond);
3724 while (!list_empty(&out->offload_cmd_list)) {
3725 item = list_head(&out->offload_cmd_list);
3726 list_remove(item);
3727 free(node_to_item(item, struct offload_cmd, node));
3728 }
3729 pthread_mutex_unlock(&out->lock);
3730
3731 return NULL;
3732}
3733
3734static int create_offload_callback_thread(struct stream_out *out)
3735{
3736 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3737 list_init(&out->offload_cmd_list);
3738 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3739 offload_thread_loop, out);
3740 return 0;
3741}
3742
3743static int destroy_offload_callback_thread(struct stream_out *out)
3744{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003745 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003746 stop_compressed_output_l(out);
3747 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3748
3749 pthread_mutex_unlock(&out->lock);
3750 pthread_join(out->offload_thread, (void **) NULL);
3751 pthread_cond_destroy(&out->offload_cond);
3752
3753 return 0;
3754}
3755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756static int stop_output_stream(struct stream_out *out)
3757{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303758 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 struct audio_usecase *uc_info;
3760 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003761 bool has_voip_usecase =
3762 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763
Eric Laurent994a6932013-07-17 11:51:42 -07003764 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003765 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 uc_info = get_usecase_from_list(adev, out->usecase);
3767 if (uc_info == NULL) {
3768 ALOGE("%s: Could not find the usecase (%d) in the list",
3769 __func__, out->usecase);
3770 return -EINVAL;
3771 }
3772
Zhou Songbaddf9f2020-11-20 13:57:39 +08003773 out->a2dp_muted = false;
3774
Derek Chenea197282019-01-07 17:35:01 -08003775 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3776 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003777
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003778 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303779 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003780 if (adev->visualizer_stop_output != NULL)
3781 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003782
3783 audio_extn_dts_remove_state_notifier_node(out->usecase);
3784
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003785 if (adev->offload_effects_stop_output != NULL)
3786 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003787 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3788 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3789 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003790 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003791
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003792 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3793 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003794 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003795 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003796
Eric Laurent150dbfe2013-02-27 14:31:02 -08003797 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003798 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003799
3800 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003801 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003802 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3803 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Aalique Grahame22e49102018-12-18 14:23:57 -08003805 audio_extn_extspk_update(adev->extspk);
3806
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003807 if (is_offload_usecase(out->usecase)) {
3808 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3809 adev->dsp_bit_width_enforce_mode,
3810 false);
3811 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003812 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003813 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3814 false);
3815
3816 if (ret != 0)
3817 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3818 /* default service interval was successfully updated,
3819 reopen USB backend with new service interval */
3820 ret = 0;
3821 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003822
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003823 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303824 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003825 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303826 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003827 ALOGV("Disable passthrough , reset mixer to pcm");
3828 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003829#ifdef AUDIO_GKI_ENABLED
3830 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3831 out->compr_config.codec->reserved[0] = 0;
3832#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003833 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003834#endif
Mingming Yin21854652016-04-13 11:54:02 -07003835 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003836 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3837 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003838
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303839 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003840 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303841 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303842
Manish Dewangan21a850a2017-08-14 12:03:55 +05303843 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003844 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3845 if (ret < 0)
3846 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3847 }
3848
Zhou Song642ec432020-12-23 16:11:10 +08003849 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003850 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003851 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003852 struct listnode *node;
3853 struct audio_usecase *usecase;
3854 list_for_each(node, &adev->usecase_list) {
3855 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003856 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3857 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303858 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003859 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003860 continue;
3861
3862 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3863 __func__, usecase->id, use_case_table[usecase->id],
3864 out->usecase, use_case_table[out->usecase]);
3865 select_devices(adev, usecase->id);
3866 }
3867 }
3868
Garmond Leung5fd0b552018-04-17 11:56:12 -07003869 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003870 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 return ret;
3872}
3873
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003874struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3875 unsigned int flags, unsigned int pcm_open_retry_count,
3876 struct pcm_config *config)
3877{
3878 struct pcm* pcm = NULL;
3879
3880 while (1) {
3881 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3882 if (pcm == NULL || !pcm_is_ready(pcm)) {
3883 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3884 if (pcm != NULL) {
3885 pcm_close(pcm);
3886 pcm = NULL;
3887 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003888 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003889 return NULL;
3890
Weiyin Jiang72197252019-10-09 11:49:32 +08003891 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003892 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3893 continue;
3894 }
3895 break;
3896 }
3897
3898 if (pcm_is_ready(pcm)) {
3899 int ret = pcm_prepare(pcm);
3900 if (ret < 0) {
3901 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3902 pcm_close(pcm);
3903 pcm = NULL;
3904 }
3905 }
3906
3907 return pcm;
3908}
3909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910int start_output_stream(struct stream_out *out)
3911{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 struct audio_usecase *uc_info;
3914 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003915 char mixer_ctl_name[128];
3916 struct mixer_ctl *ctl = NULL;
3917 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303918 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003919 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920
Haynes Mathew George380745d2017-10-04 15:27:45 -07003921 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003922 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3923 ret = -EINVAL;
3924 goto error_config;
3925 }
3926
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003927 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303928 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003929 get_device_types(&out->device_list), is_haptic_usecase);
3930
3931 bool is_speaker_active = compare_device_type(&out->device_list,
3932 AUDIO_DEVICE_OUT_SPEAKER);
3933 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3934 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303935
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303936 if (CARD_STATUS_OFFLINE == out->card_status ||
3937 CARD_STATUS_OFFLINE == adev->card_status) {
3938 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303939 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003940 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303941 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303942
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003943 //Update incall music usecase to reflect correct voice session
3944 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3945 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3946 if (ret != 0) {
3947 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3948 __func__, ret);
3949 goto error_config;
3950 }
3951 }
3952
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003953 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003954 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003955 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303956 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303957 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003958 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303959 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3960 ret = -EAGAIN;
3961 goto error_config;
3962 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303963 }
3964 }
3965 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003966 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303967 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003968 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303969 //combo usecase just by pass a2dp
3970 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003971 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303972 } else {
3973 ALOGE("%s: SCO profile is not ready, return error", __func__);
3974 ret = -EAGAIN;
3975 goto error_config;
3976 }
3977 }
3978 }
3979
Eric Laurentb23d5282013-05-14 15:27:20 -07003980 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981 if (out->pcm_device_id < 0) {
3982 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3983 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003984 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003985 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 }
3987
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003988 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003989 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3990 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003991 if (adev->haptic_pcm_device_id < 0) {
3992 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3993 __func__, adev->haptic_pcm_device_id, out->usecase);
3994 ret = -EINVAL;
3995 goto error_config;
3996 }
3997 }
3998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004000
4001 if (!uc_info) {
4002 ret = -ENOMEM;
4003 goto error_config;
4004 }
4005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006 uc_info->id = out->usecase;
4007 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004008 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004009 list_init(&uc_info->device_list);
4010 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004011 uc_info->in_snd_device = SND_DEVICE_NONE;
4012 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004013
4014 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004015 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004016 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4017 /* USB backend is not reopened immediately.
4018 This is eventually done as part of select_devices */
4019 }
4020
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004021 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022
Wei Wangf7ca6c92017-11-21 14:51:20 -08004023 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304024 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4025 adev->perf_lock_opts,
4026 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304027
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004028 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304029 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304030 if (audio_extn_passthru_is_enabled() &&
4031 audio_extn_passthru_is_passthrough_stream(out)) {
4032 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304033 }
4034 }
4035
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004036 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004037 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304038 if (!a2dp_combo) {
4039 check_a2dp_restore_l(adev, out, false);
4040 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004041 struct listnode dev;
4042 list_init(&dev);
4043 assign_devices(&dev, &out->device_list);
4044 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4045 reassign_device_list(&out->device_list,
4046 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004047 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004048 reassign_device_list(&out->device_list,
4049 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304050 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004051 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304052 }
4053 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304054 select_devices(adev, out->usecase);
4055 if (is_a2dp_out_device_type(&out->device_list) &&
4056 !adev->a2dp_started) {
4057 if (is_speaker_active || is_speaker_safe_active) {
4058 struct listnode dev;
4059 list_init(&dev);
4060 assign_devices(&dev, &out->device_list);
4061 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4062 reassign_device_list(&out->device_list,
4063 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4064 else
4065 reassign_device_list(&out->device_list,
4066 AUDIO_DEVICE_OUT_SPEAKER, "");
4067 select_devices(adev, out->usecase);
4068 assign_devices(&out->device_list, &dev);
4069 } else {
4070 ret = -EINVAL;
4071 goto error_open;
4072 }
4073 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304074 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004075
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004076 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4077 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004078 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004079 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004080
Derek Chenea197282019-01-07 17:35:01 -08004081 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4082 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004083
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004084 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4085 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004086
4087 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004088 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004089 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4090 ALOGE("%s: pcm stream not ready", __func__);
4091 goto error_open;
4092 }
4093 ret = pcm_start(out->pcm);
4094 if (ret < 0) {
4095 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4096 goto error_open;
4097 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004098 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004099 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004100 unsigned int flags = PCM_OUT;
4101 unsigned int pcm_open_retry_count = 0;
4102 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4103 flags |= PCM_MMAP | PCM_NOIRQ;
4104 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004105 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004106 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004107 } else
4108 flags |= PCM_MONOTONIC;
4109
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004110 if ((adev->vr_audio_mode_enabled) &&
4111 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4112 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4113 "PCM_Dev %d Topology", out->pcm_device_id);
4114 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4115 if (!ctl) {
4116 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4117 __func__, mixer_ctl_name);
4118 } else {
4119 //if success use ULLPP
4120 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4121 __func__, mixer_ctl_name, out->pcm_device_id);
4122 //There is a still a possibility that some sessions
4123 // that request for FAST|RAW when 3D audio is active
4124 //can go through ULLPP. Ideally we expects apps to
4125 //listen to audio focus and stop concurrent playback
4126 //Also, we will look for mode flag (voice_in_communication)
4127 //before enabling the realtime flag.
4128 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4129 }
4130 }
4131
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304132 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4133 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304134
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004135 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4136 flags, pcm_open_retry_count,
4137 &(out->config));
4138 if (out->pcm == NULL) {
4139 ret = -EIO;
4140 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004141 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004142
4143 if (is_haptic_usecase) {
4144 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4145 adev->haptic_pcm_device_id,
4146 flags, pcm_open_retry_count,
4147 &(adev->haptics_config));
4148 // failure to open haptics pcm shouldnt stop audio,
4149 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004150
4151 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4152 ALOGD("%s: enable haptic audio synchronization", __func__);
4153 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4154 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004155 }
4156
Zhou Song2b8f28f2017-09-11 10:51:38 +08004157 // apply volume for voip playback after path is set up
4158 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4159 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304160 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4161 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304162 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4163 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004164 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4165 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304166 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004167 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004168 /*
4169 * set custom channel map if:
4170 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4171 * 2. custom channel map has been set by client
4172 * else default channel map of FC/FR/FL can always be set to DSP
4173 */
4174 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4175 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004176 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004177 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4178 adev->dsp_bit_width_enforce_mode,
4179 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004181 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004182 out->compr = compress_open(adev->snd_card,
4183 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004184 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004185 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304186 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304187 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4188 adev->card_status = CARD_STATUS_OFFLINE;
4189 out->card_status = CARD_STATUS_OFFLINE;
4190 ret = -EIO;
4191 goto error_open;
4192 }
4193
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004194 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004195 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004196 compress_close(out->compr);
4197 out->compr = NULL;
4198 ret = -EIO;
4199 goto error_open;
4200 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304201 /* compress_open sends params of the track, so reset the flag here */
4202 out->is_compr_metadata_avail = false;
4203
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004204 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004205 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004206
Fred Oh3f43e742015-03-04 18:42:34 -08004207 /* Since small bufs uses blocking writes, a write will be blocked
4208 for the default max poll time (20s) in the event of an SSR.
4209 Reduce the poll time to observe and deal with SSR faster.
4210 */
Ashish Jain5106d362016-05-11 19:23:33 +05304211 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004212 compress_set_max_poll_wait(out->compr, 1000);
4213 }
4214
Manish Dewangan69426c82017-01-30 17:35:36 +05304215 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304216 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304217
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004218 audio_extn_dts_create_state_notifier_node(out->usecase);
4219 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4220 popcount(out->channel_mask),
4221 out->playback_started);
4222
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004223#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304224 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004225 audio_extn_dolby_send_ddp_endp_params(adev);
4226#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304227 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4228 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004229 if (adev->visualizer_start_output != NULL)
4230 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4231 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304232 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004233 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004234 }
Derek Chenf13dd492018-11-13 14:53:51 -08004235
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004236 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004237 /* Update cached volume from media to offload/direct stream */
4238 struct listnode *node = NULL;
4239 list_for_each(node, &adev->active_outputs_list) {
4240 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4241 streams_output_ctxt_t,
4242 list);
4243 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4244 out->volume_l = out_ctxt->output->volume_l;
4245 out->volume_r = out_ctxt->output->volume_r;
4246 }
4247 }
4248 out_set_compr_volume(&out->stream,
4249 out->volume_l, out->volume_r);
4250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004252
4253 if (ret == 0) {
4254 register_out_stream(out);
4255 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004256 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4257 ALOGE("%s: pcm stream not ready", __func__);
4258 goto error_open;
4259 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004260 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004261 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004262 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004263 if (ret < 0)
4264 goto error_open;
4265 }
4266 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004267 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304268 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304269 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004270
vivek mehtad15d2bf2019-05-17 13:35:10 -07004271 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4272 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4273 audio_low_latency_hint_start();
4274 }
4275
Manish Dewangan21a850a2017-08-14 12:03:55 +05304276 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004277 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004278 if (ret < 0)
4279 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4280 }
4281
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004282 // consider a scenario where on pause lower layers are tear down.
4283 // so on resume, swap mixer control need to be sent only when
4284 // backend is active, hence rather than sending from enable device
4285 // sending it from start of streamtream
4286
4287 platform_set_swap_channels(adev, true);
4288
Haynes Mathew George380745d2017-10-04 15:27:45 -07004289 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304290 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004291 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004292error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004293 if (adev->haptic_pcm) {
4294 pcm_close(adev->haptic_pcm);
4295 adev->haptic_pcm = NULL;
4296 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004297 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304298 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004300error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304301 /*
4302 * sleep 50ms to allow sufficient time for kernel
4303 * drivers to recover incases like SSR.
4304 */
4305 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004306error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004307 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304308 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004309 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310}
4311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312static int check_input_parameters(uint32_t sample_rate,
4313 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004314 int channel_count,
4315 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004317 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304319 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4320 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4321 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004322 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004323 !audio_extn_compr_cap_format_supported(format) &&
4324 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004325 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004326
Aalique Grahame22e49102018-12-18 14:23:57 -08004327 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4328 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4329 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4330 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4331 return -EINVAL;
4332 }
4333
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004334 switch (channel_count) {
4335 case 1:
4336 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304337 case 3:
4338 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004339 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004340 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304341 case 10:
4342 case 12:
4343 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004344 break;
4345 default:
4346 ret = -EINVAL;
4347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348
4349 switch (sample_rate) {
4350 case 8000:
4351 case 11025:
4352 case 12000:
4353 case 16000:
4354 case 22050:
4355 case 24000:
4356 case 32000:
4357 case 44100:
4358 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004359 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304360 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004361 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304362 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 break;
4364 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004365 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366 }
4367
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004368 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369}
4370
Naresh Tanniru04f71882018-06-26 17:46:22 +05304371
4372/** Add a value in a list if not already present.
4373 * @return true if value was successfully inserted or already present,
4374 * false if the list is full and does not contain the value.
4375 */
4376static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4377 for (size_t i = 0; i < list_length; i++) {
4378 if (list[i] == value) return true; // value is already present
4379 if (list[i] == 0) { // no values in this slot
4380 list[i] = value;
4381 return true; // value inserted
4382 }
4383 }
4384 return false; // could not insert value
4385}
4386
4387/** Add channel_mask in supported_channel_masks if not already present.
4388 * @return true if channel_mask was successfully inserted or already present,
4389 * false if supported_channel_masks is full and does not contain channel_mask.
4390 */
4391static void register_channel_mask(audio_channel_mask_t channel_mask,
4392 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4393 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4394 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4395}
4396
4397/** Add format in supported_formats if not already present.
4398 * @return true if format was successfully inserted or already present,
4399 * false if supported_formats is full and does not contain format.
4400 */
4401static void register_format(audio_format_t format,
4402 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4403 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4404 "%s: stream can not declare supporting its format %x", __func__, format);
4405}
4406/** Add sample_rate in supported_sample_rates if not already present.
4407 * @return true if sample_rate was successfully inserted or already present,
4408 * false if supported_sample_rates is full and does not contain sample_rate.
4409 */
4410static void register_sample_rate(uint32_t sample_rate,
4411 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4412 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4413 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4414}
4415
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004416static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4417{
4418 uint32_t high = num1, low = num2, temp = 0;
4419
4420 if (!num1 || !num2)
4421 return 0;
4422
4423 if (num1 < num2) {
4424 high = num2;
4425 low = num1;
4426 }
4427
4428 while (low != 0) {
4429 temp = low;
4430 low = high % low;
4431 high = temp;
4432 }
4433 return (num1 * num2)/high;
4434}
4435
4436static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4437{
4438 uint32_t remainder = 0;
4439
4440 if (!multiplier)
4441 return num;
4442
4443 remainder = num % multiplier;
4444 if (remainder)
4445 num += (multiplier - remainder);
4446
4447 return num;
4448}
4449
Aalique Grahame22e49102018-12-18 14:23:57 -08004450static size_t get_stream_buffer_size(size_t duration_ms,
4451 uint32_t sample_rate,
4452 audio_format_t format,
4453 int channel_count,
4454 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455{
4456 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004457 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458
Aalique Grahame22e49102018-12-18 14:23:57 -08004459 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004460 if (is_low_latency)
4461 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304462
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004463 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004464 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465
Ralf Herzbd08d632018-09-28 15:50:49 +02004466 /* make sure the size is multiple of 32 bytes and additionally multiple of
4467 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004468 * At 48 kHz mono 16-bit PCM:
4469 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4470 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004471 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004472 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004473 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004474
4475 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476}
4477
Aalique Grahame22e49102018-12-18 14:23:57 -08004478static size_t get_input_buffer_size(uint32_t sample_rate,
4479 audio_format_t format,
4480 int channel_count,
4481 bool is_low_latency)
4482{
4483 /* Don't know if USB HIFI in this context so use true to be conservative */
4484 if (check_input_parameters(sample_rate, format, channel_count,
4485 true /*is_usb_hifi */) != 0)
4486 return 0;
4487
4488 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4489 sample_rate,
4490 format,
4491 channel_count,
4492 is_low_latency);
4493}
4494
Derek Chenf6318be2017-06-12 17:16:24 -04004495size_t get_output_period_size(uint32_t sample_rate,
4496 audio_format_t format,
4497 int channel_count,
4498 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304499{
4500 size_t size = 0;
4501 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4502
4503 if ((duration == 0) || (sample_rate == 0) ||
4504 (bytes_per_sample == 0) || (channel_count == 0)) {
4505 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4506 bytes_per_sample, channel_count);
4507 return -EINVAL;
4508 }
4509
4510 size = (sample_rate *
4511 duration *
4512 bytes_per_sample *
4513 channel_count) / 1000;
4514 /*
4515 * To have same PCM samples for all channels, the buffer size requires to
4516 * be multiple of (number of channels * bytes per sample)
4517 * For writes to succeed, the buffer must be written at address which is multiple of 32
4518 */
4519 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4520
4521 return (size/(channel_count * bytes_per_sample));
4522}
4523
Zhou Song48453a02018-01-10 17:50:59 +08004524static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304525{
4526 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004527 uint64_t written_frames = 0;
4528 uint64_t kernel_frames = 0;
4529 uint64_t dsp_frames = 0;
4530 uint64_t signed_frames = 0;
4531 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304532
4533 /* This adjustment accounts for buffering after app processor.
4534 * It is based on estimated DSP latency per use case, rather than exact.
4535 */
George Gao9ba8a142020-07-23 14:30:03 -07004536 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004537 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304538
Zhou Song48453a02018-01-10 17:50:59 +08004539 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004540 written_frames = out->written /
4541 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4542
Ashish Jain5106d362016-05-11 19:23:33 +05304543 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4544 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4545 * hence only estimate.
4546 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004547 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4548 kernel_frames = kernel_buffer_size /
4549 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304550
Weiyin Jiang4813da12020-05-28 00:37:28 +08004551 if (written_frames >= (kernel_frames + dsp_frames))
4552 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304553
Zhou Song48453a02018-01-10 17:50:59 +08004554 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304555 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004556 if (timestamp != NULL )
4557 *timestamp = out->writeAt;
4558 } else if (timestamp != NULL) {
4559 clock_gettime(CLOCK_MONOTONIC, timestamp);
4560 }
4561 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304562
Weiyin Jiang4813da12020-05-28 00:37:28 +08004563 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4564 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304565
4566 return actual_frames_rendered;
4567}
4568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4570{
4571 struct stream_out *out = (struct stream_out *)stream;
4572
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004573 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574}
4575
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004576static int out_set_sample_rate(struct audio_stream *stream __unused,
4577 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578{
4579 return -ENOSYS;
4580}
4581
4582static size_t out_get_buffer_size(const struct audio_stream *stream)
4583{
4584 struct stream_out *out = (struct stream_out *)stream;
4585
Varun Balaraje49253e2017-07-06 19:48:56 +05304586 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304587 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304588 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304589 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4590 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4591 else
4592 return out->compr_config.fragment_size;
4593 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004594 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304595 else if (is_offload_usecase(out->usecase) &&
4596 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304597 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004598
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004599 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004600 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601}
4602
4603static uint32_t out_get_channels(const struct audio_stream *stream)
4604{
4605 struct stream_out *out = (struct stream_out *)stream;
4606
4607 return out->channel_mask;
4608}
4609
4610static audio_format_t out_get_format(const struct audio_stream *stream)
4611{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004612 struct stream_out *out = (struct stream_out *)stream;
4613
4614 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615}
4616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004617static int out_set_format(struct audio_stream *stream __unused,
4618 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004619{
4620 return -ENOSYS;
4621}
4622
4623static int out_standby(struct audio_stream *stream)
4624{
4625 struct stream_out *out = (struct stream_out *)stream;
4626 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004627 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004628
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304629 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4630 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004632 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004634 if (adev->adm_deregister_stream)
4635 adev->adm_deregister_stream(adev->adm_data, out->handle);
4636
Weiyin Jiang280ea742020-09-08 20:28:22 +08004637 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004638 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004639 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004640
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004641 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004643 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4644 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304645 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004646 pthread_mutex_unlock(&adev->lock);
4647 pthread_mutex_unlock(&out->lock);
4648 ALOGD("VOIP output entered standby");
4649 return 0;
4650 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004651 if (out->pcm) {
4652 pcm_close(out->pcm);
4653 out->pcm = NULL;
4654 }
Meng Wanga09da002020-04-20 12:56:04 +08004655 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4656 if (adev->haptic_pcm) {
4657 pcm_close(adev->haptic_pcm);
4658 adev->haptic_pcm = NULL;
4659 }
4660
4661 if (adev->haptic_buffer != NULL) {
4662 free(adev->haptic_buffer);
4663 adev->haptic_buffer = NULL;
4664 adev->haptic_buffer_size = 0;
4665 }
4666 adev->haptic_pcm_device_id = 0;
4667 }
4668
Haynes Mathew George16081042017-05-31 17:16:49 -07004669 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4670 do_stop = out->playback_started;
4671 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004672
4673 if (out->mmap_shared_memory_fd >= 0) {
4674 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4675 __func__, out->mmap_shared_memory_fd);
4676 close(out->mmap_shared_memory_fd);
4677 out->mmap_shared_memory_fd = -1;
4678 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004679 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004680 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004681 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304682 out->send_next_track_params = false;
4683 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004684 out->gapless_mdata.encoder_delay = 0;
4685 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004686 if (out->compr != NULL) {
4687 compress_close(out->compr);
4688 out->compr = NULL;
4689 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004690 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004691 if (do_stop) {
4692 stop_output_stream(out);
4693 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304694 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004695 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004696 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 }
4698 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004699 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 return 0;
4701}
4702
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304703static int out_on_error(struct audio_stream *stream)
4704{
4705 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004706 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304707
4708 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004709 // always send CMD_ERROR for offload streams, this
4710 // is needed e.g. when SSR happens within compress_open
4711 // since the stream is active, offload_callback_thread is also active.
4712 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4713 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004714 }
4715 pthread_mutex_unlock(&out->lock);
4716
4717 status = out_standby(&out->stream.common);
4718
4719 lock_output_stream(out);
4720 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004721 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304722 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304723
4724 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4725 ALOGD("Setting previous card status if offline");
4726 out->prev_card_status_offline = true;
4727 }
4728
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304729 pthread_mutex_unlock(&out->lock);
4730
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004731 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304732}
4733
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304734/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004735 * standby implementation without locks, assumes that the callee already
4736 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304737 */
4738int out_standby_l(struct audio_stream *stream)
4739{
4740 struct stream_out *out = (struct stream_out *)stream;
4741 struct audio_device *adev = out->dev;
4742
4743 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4744 stream, out->usecase, use_case_table[out->usecase]);
4745
4746 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004747 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304748 if (adev->adm_deregister_stream)
4749 adev->adm_deregister_stream(adev->adm_data, out->handle);
4750
Weiyin Jiang280ea742020-09-08 20:28:22 +08004751 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304752 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004753 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304754
4755 out->standby = true;
4756 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4757 voice_extn_compress_voip_close_output_stream(stream);
4758 out->started = 0;
4759 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004760 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304761 return 0;
4762 } else if (!is_offload_usecase(out->usecase)) {
4763 if (out->pcm) {
4764 pcm_close(out->pcm);
4765 out->pcm = NULL;
4766 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004767 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4768 if (adev->haptic_pcm) {
4769 pcm_close(adev->haptic_pcm);
4770 adev->haptic_pcm = NULL;
4771 }
4772
4773 if (adev->haptic_buffer != NULL) {
4774 free(adev->haptic_buffer);
4775 adev->haptic_buffer = NULL;
4776 adev->haptic_buffer_size = 0;
4777 }
4778 adev->haptic_pcm_device_id = 0;
4779 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304780 } else {
4781 ALOGD("copl(%p):standby", out);
4782 out->send_next_track_params = false;
4783 out->is_compr_metadata_avail = false;
4784 out->gapless_mdata.encoder_delay = 0;
4785 out->gapless_mdata.encoder_padding = 0;
4786 if (out->compr != NULL) {
4787 compress_close(out->compr);
4788 out->compr = NULL;
4789 }
4790 }
4791 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004792 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304793 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004794 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304795 return 0;
4796}
4797
Aalique Grahame22e49102018-12-18 14:23:57 -08004798static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799{
Aalique Grahame22e49102018-12-18 14:23:57 -08004800 struct stream_out *out = (struct stream_out *)stream;
4801
4802 // We try to get the lock for consistency,
4803 // but it isn't necessary for these variables.
4804 // If we're not in standby, we may be blocked on a write.
4805 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4806 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4807 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4808
Andy Hunga1f48fa2019-07-01 18:14:53 -07004809 char buffer[256]; // for statistics formatting
4810 if (!is_offload_usecase(out->usecase)) {
4811 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4812 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4813 }
4814
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004815 if (out->start_latency_ms.n > 0) {
4816 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4817 dprintf(fd, " Start latency ms: %s\n", buffer);
4818 }
4819
Aalique Grahame22e49102018-12-18 14:23:57 -08004820 if (locked) {
4821 pthread_mutex_unlock(&out->lock);
4822 }
4823
4824 // dump error info
4825 (void)error_log_dump(
4826 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828 return 0;
4829}
4830
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004831static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4832{
4833 int ret = 0;
4834 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004835
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004836 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004837 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004838 return -EINVAL;
4839 }
4840
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304841 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004842
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4844 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304845 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004846 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004847 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4848 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304849 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004850 }
4851
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004852 ALOGV("%s new encoder delay %u and padding %u", __func__,
4853 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4854
4855 return 0;
4856}
4857
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004858static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4859{
4860 return out == adev->primary_output || out == adev->voice_tx_output;
4861}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004862
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304863// note: this call is safe only if the stream_cb is
4864// removed first in close_output_stream (as is done now).
4865static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4866{
4867 if (!stream || !parms)
4868 return;
4869
4870 struct stream_out *out = (struct stream_out *)stream;
4871 struct audio_device *adev = out->dev;
4872
4873 card_status_t status;
4874 int card;
4875 if (parse_snd_card_status(parms, &card, &status) < 0)
4876 return;
4877
4878 pthread_mutex_lock(&adev->lock);
4879 bool valid_cb = (card == adev->snd_card);
4880 pthread_mutex_unlock(&adev->lock);
4881
4882 if (!valid_cb)
4883 return;
4884
4885 lock_output_stream(out);
4886 if (out->card_status != status)
4887 out->card_status = status;
4888 pthread_mutex_unlock(&out->lock);
4889
4890 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4891 use_case_table[out->usecase],
4892 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4893
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304894 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304895 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304896 if (voice_is_call_state_active(adev) &&
4897 out == adev->primary_output) {
4898 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4899 pthread_mutex_lock(&adev->lock);
4900 voice_stop_call(adev);
4901 adev->mode = AUDIO_MODE_NORMAL;
4902 pthread_mutex_unlock(&adev->lock);
4903 }
4904 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304905 return;
4906}
4907
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004908int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004909 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004910{
4911 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004912 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004913 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004914 bool bypass_a2dp = false;
4915 bool reconfig = false;
4916 unsigned long service_interval = 0;
4917
4918 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004919 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4920
4921 list_init(&new_devices);
4922 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004923
4924 lock_output_stream(out);
4925 pthread_mutex_lock(&adev->lock);
4926
4927 /*
4928 * When HDMI cable is unplugged the music playback is paused and
4929 * the policy manager sends routing=0. But the audioflinger continues
4930 * to write data until standby time (3sec). As the HDMI core is
4931 * turned off, the write gets blocked.
4932 * Avoid this by routing audio to speaker until standby.
4933 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004934 if (is_single_device_type_equal(&out->device_list,
4935 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004936 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004937 !audio_extn_passthru_is_passthrough_stream(out) &&
4938 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004939 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004940 }
4941 /*
4942 * When A2DP is disconnected the
4943 * music playback is paused and the policy manager sends routing=0
4944 * But the audioflinger continues to write data until standby time
4945 * (3sec). As BT is turned off, the write gets blocked.
4946 * Avoid this by routing audio to speaker until standby.
4947 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004948 if (is_a2dp_out_device_type(&out->device_list) &&
4949 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004950 !audio_extn_a2dp_source_is_ready() &&
4951 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004952 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004953 }
4954 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08004955 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004956 * and the policy manager send routing=0. But if the USB is connected
4957 * back before the standby time, AFE is not closed and opened
4958 * when USB is connected back. So routing to speker will guarantee
4959 * AFE reconfiguration and AFE will be opend once USB is connected again
4960 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004961 if (is_usb_out_device_type(&out->device_list) &&
4962 list_empty(&new_devices) &&
4963 !audio_extn_usb_connected(NULL)) {
Sujin Panicker84d953a2020-11-16 17:39:54 +05304964 if (adev->mode == AUDIO_MODE_IN_CALL || adev->mode == AUDIO_MODE_IN_COMMUNICATION)
4965 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_EARPIECE, "");
4966 else
4967 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004968 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004969 /* To avoid a2dp to sco overlapping / BT device improper state
4970 * check with BT lib about a2dp streaming support before routing
4971 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004972 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004973 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004974 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4975 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004976 //combo usecase just by pass a2dp
4977 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4978 bypass_a2dp = true;
4979 } else {
4980 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4981 /* update device to a2dp and don't route as BT returned error
4982 * However it is still possible a2dp routing called because
4983 * of current active device disconnection (like wired headset)
4984 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004985 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 pthread_mutex_unlock(&adev->lock);
4987 pthread_mutex_unlock(&out->lock);
4988 goto error;
4989 }
4990 }
4991 }
4992
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004993 // Workaround: If routing to an non existing usb device, fail gracefully
4994 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004995 if (is_usb_out_device_type(&new_devices)) {
4996 struct str_parms *parms =
4997 str_parms_create_str(get_usb_device_address(&new_devices));
4998 if (!parms)
4999 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08005000 if (!audio_extn_usb_connected(NULL)) {
5001 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005002 pthread_mutex_unlock(&adev->lock);
5003 pthread_mutex_unlock(&out->lock);
5004 str_parms_destroy(parms);
5005 ret = -ENOSYS;
5006 goto error;
5007 }
5008 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005009 }
5010
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005011 // Workaround: If routing to an non existing hdmi device, fail gracefully
5012 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5013 (platform_get_edid_info_v2(adev->platform,
5014 out->extconn.cs.controller,
5015 out->extconn.cs.stream) != 0)) {
5016 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5017 pthread_mutex_unlock(&adev->lock);
5018 pthread_mutex_unlock(&out->lock);
5019 ret = -ENOSYS;
5020 goto error;
5021 }
5022
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005023 /*
5024 * select_devices() call below switches all the usecases on the same
5025 * backend to the new device. Refer to check_usecases_codec_backend() in
5026 * the select_devices(). But how do we undo this?
5027 *
5028 * For example, music playback is active on headset (deep-buffer usecase)
5029 * and if we go to ringtones and select a ringtone, low-latency usecase
5030 * will be started on headset+speaker. As we can't enable headset+speaker
5031 * and headset devices at the same time, select_devices() switches the music
5032 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5033 * So when the ringtone playback is completed, how do we undo the same?
5034 *
5035 * We are relying on the out_set_parameters() call on deep-buffer output,
5036 * once the ringtone playback is ended.
5037 * NOTE: We should not check if the current devices are same as new devices.
5038 * Because select_devices() must be called to switch back the music
5039 * playback to headset.
5040 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005041 if (!list_empty(&new_devices)) {
5042 bool same_dev = compare_devices(&out->device_list, &new_devices);
5043 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005044
5045 if (output_drives_call(adev, out)) {
5046 if (!voice_is_call_state_active(adev)) {
5047 if (adev->mode == AUDIO_MODE_IN_CALL) {
5048 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005049 ret = voice_start_call(adev);
5050 }
5051 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005052 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005053 adev->current_call_output = out;
5054 voice_update_devices_for_all_voice_usecases(adev);
5055 }
5056 }
5057
Mingshu Pang971ff702020-09-09 15:28:22 +08005058 if (is_usb_out_device_type(&out->device_list)) {
5059 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5060 audio_extn_usb_set_service_interval(true /*playback*/,
5061 service_interval,
5062 &reconfig);
5063 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5064 }
5065
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005066 if (!out->standby) {
5067 if (!same_dev) {
5068 ALOGV("update routing change");
5069 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5070 adev->perf_lock_opts,
5071 adev->perf_lock_opts_size);
5072 if (adev->adm_on_routing_change)
5073 adev->adm_on_routing_change(adev->adm_data,
5074 out->handle);
5075 }
5076 if (!bypass_a2dp) {
5077 select_devices(adev, out->usecase);
5078 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005079 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5080 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005081 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005082 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005083 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005084 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005085 }
5086
5087 if (!same_dev) {
5088 // on device switch force swap, lower functions will make sure
5089 // to check if swap is allowed or not.
5090 platform_set_swap_channels(adev, true);
5091 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5092 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005093 pthread_mutex_lock(&out->latch_lock);
5094 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5095 if (out->a2dp_muted) {
5096 out->a2dp_muted = false;
5097 if (is_offload_usecase(out->usecase))
5098 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5099 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5100 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005101 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005102 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005103 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5104 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5105 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005106 }
5107 }
5108
5109 pthread_mutex_unlock(&adev->lock);
5110 pthread_mutex_unlock(&out->lock);
5111
5112 /*handles device and call state changes*/
5113 audio_extn_extspk_update(adev->extspk);
5114
5115error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005116 ALOGV("%s: exit: code(%d)", __func__, ret);
5117 return ret;
5118}
5119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005120static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5121{
5122 struct stream_out *out = (struct stream_out *)stream;
5123 struct audio_device *adev = out->dev;
5124 struct str_parms *parms;
5125 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005126 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005127 int ext_controller = -1;
5128 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129
sangwoobc677242013-08-08 16:53:43 +09005130 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005131 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005132 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305133 if (!parms)
5134 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005135
5136 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5137 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005138 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005139 out->extconn.cs.controller = ext_controller;
5140 out->extconn.cs.stream = ext_stream;
5141 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5142 use_case_table[out->usecase], out->extconn.cs.controller,
5143 out->extconn.cs.stream);
5144 }
5145
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005146 if (out == adev->primary_output) {
5147 pthread_mutex_lock(&adev->lock);
5148 audio_extn_set_parameters(adev, parms);
5149 pthread_mutex_unlock(&adev->lock);
5150 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005151 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005152 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005153 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005154
5155 audio_extn_dts_create_state_notifier_node(out->usecase);
5156 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5157 popcount(out->channel_mask),
5158 out->playback_started);
5159
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005160 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005161 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005162
Surendar Karkaf51b5842018-04-26 11:28:38 +05305163 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5164 sizeof(value));
5165 if (err >= 0) {
5166 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5167 audio_extn_send_dual_mono_mixing_coefficients(out);
5168 }
5169
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305170 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5171 if (err >= 0) {
5172 strlcpy(out->profile, value, sizeof(out->profile));
5173 ALOGV("updating stream profile with value '%s'", out->profile);
5174 lock_output_stream(out);
5175 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5176 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005177 &out->device_list, out->flags,
5178 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305179 out->sample_rate, out->bit_width,
5180 out->channel_mask, out->profile,
5181 &out->app_type_cfg);
5182 pthread_mutex_unlock(&out->lock);
5183 }
5184
Alexy Joseph98988832017-01-13 14:56:59 -08005185 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005186 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5187 // and vendor.audio.hal.output.suspend.supported is set to true
5188 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005189 //check suspend parameter only for low latency and if the property
5190 //is enabled
5191 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5192 ALOGI("%s: got suspend_playback %s", __func__, value);
5193 lock_output_stream(out);
5194 if (!strncmp(value, "false", 5)) {
5195 //suspend_playback=false is supposed to set QOS value back to 75%
5196 //the mixer control sent with value Enable will achieve that
5197 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5198 } else if (!strncmp (value, "true", 4)) {
5199 //suspend_playback=true is supposed to remove QOS value
5200 //resetting the mixer control will set the default value
5201 //for the mixer control which is Disable and this removes the QOS vote
5202 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5203 } else {
5204 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5205 " got %s", __func__, value);
5206 ret = -1;
5207 }
5208
5209 if (ret != 0) {
5210 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5211 __func__, out->pm_qos_mixer_path, ret);
5212 }
5213
5214 pthread_mutex_unlock(&out->lock);
5215 }
5216 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005217
Alexy Joseph98988832017-01-13 14:56:59 -08005218 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005219 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305220error:
Eric Laurent994a6932013-07-17 11:51:42 -07005221 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222 return ret;
5223}
5224
Paul McLeana50b7332018-12-17 08:24:21 -07005225static int in_set_microphone_direction(const struct audio_stream_in *stream,
5226 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005227 struct stream_in *in = (struct stream_in *)stream;
5228
5229 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5230
5231 in->direction = dir;
5232
5233 if (in->standby)
5234 return 0;
5235
5236 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005237}
5238
5239static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005240 struct stream_in *in = (struct stream_in *)stream;
5241
5242 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5243
5244 if (zoom > 1.0 || zoom < -1.0)
5245 return -EINVAL;
5246
5247 in->zoom = zoom;
5248
5249 if (in->standby)
5250 return 0;
5251
5252 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005253}
5254
5255
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005256static bool stream_get_parameter_channels(struct str_parms *query,
5257 struct str_parms *reply,
5258 audio_channel_mask_t *supported_channel_masks) {
5259 int ret = -1;
5260 char value[512];
5261 bool first = true;
5262 size_t i, j;
5263
5264 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5265 ret = 0;
5266 value[0] = '\0';
5267 i = 0;
5268 while (supported_channel_masks[i] != 0) {
5269 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5270 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5271 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305272 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005273
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305274 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005275 first = false;
5276 break;
5277 }
5278 }
5279 i++;
5280 }
5281 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5282 }
5283 return ret == 0;
5284}
5285
5286static bool stream_get_parameter_formats(struct str_parms *query,
5287 struct str_parms *reply,
5288 audio_format_t *supported_formats) {
5289 int ret = -1;
5290 char value[256];
5291 size_t i, j;
5292 bool first = true;
5293
5294 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5295 ret = 0;
5296 value[0] = '\0';
5297 i = 0;
5298 while (supported_formats[i] != 0) {
5299 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5300 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5301 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305302 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005303 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305304 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005305 first = false;
5306 break;
5307 }
5308 }
5309 i++;
5310 }
5311 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5312 }
5313 return ret == 0;
5314}
5315
5316static bool stream_get_parameter_rates(struct str_parms *query,
5317 struct str_parms *reply,
5318 uint32_t *supported_sample_rates) {
5319
5320 int i;
5321 char value[256];
5322 int ret = -1;
5323 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5324 ret = 0;
5325 value[0] = '\0';
5326 i=0;
5327 int cursor = 0;
5328 while (supported_sample_rates[i]) {
5329 int avail = sizeof(value) - cursor;
5330 ret = snprintf(value + cursor, avail, "%s%d",
5331 cursor > 0 ? "|" : "",
5332 supported_sample_rates[i]);
5333 if (ret < 0 || ret >= avail) {
5334 // if cursor is at the last element of the array
5335 // overwrite with \0 is duplicate work as
5336 // snprintf already put a \0 in place.
5337 // else
5338 // we had space to write the '|' at value[cursor]
5339 // (which will be overwritten) or no space to fill
5340 // the first element (=> cursor == 0)
5341 value[cursor] = '\0';
5342 break;
5343 }
5344 cursor += ret;
5345 ++i;
5346 }
5347 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5348 value);
5349 }
5350 return ret >= 0;
5351}
5352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5354{
5355 struct stream_out *out = (struct stream_out *)stream;
5356 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005357 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358 char value[256];
5359 struct str_parms *reply = str_parms_create();
5360 size_t i, j;
5361 int ret;
5362 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005363
5364 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005365 if (reply) {
5366 str_parms_destroy(reply);
5367 }
5368 if (query) {
5369 str_parms_destroy(query);
5370 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005371 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5372 return NULL;
5373 }
5374
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005375 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5377 if (ret >= 0) {
5378 value[0] = '\0';
5379 i = 0;
5380 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005381 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5382 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005383 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005384 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005385 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005386 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387 first = false;
5388 break;
5389 }
5390 }
5391 i++;
5392 }
5393 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5394 str = str_parms_to_str(reply);
5395 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005396 voice_extn_out_get_parameters(out, query, reply);
5397 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005398 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005399
Alexy Joseph62142aa2015-11-16 15:10:34 -08005400
5401 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5402 if (ret >= 0) {
5403 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305404 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5405 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005406 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305407 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005408 } else {
5409 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305410 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005411 }
5412 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005413 if (str)
5414 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005415 str = str_parms_to_str(reply);
5416 }
5417
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005418 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5419 if (ret >= 0) {
5420 value[0] = '\0';
5421 i = 0;
5422 first = true;
5423 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005424 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5425 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005426 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005427 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005428 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005429 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005430 first = false;
5431 break;
5432 }
5433 }
5434 i++;
5435 }
5436 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005437 if (str)
5438 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005439 str = str_parms_to_str(reply);
5440 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005441
5442 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5443 if (ret >= 0) {
5444 value[0] = '\0';
5445 i = 0;
5446 first = true;
5447 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005448 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5449 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005450 if (!first) {
5451 strlcat(value, "|", sizeof(value));
5452 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005453 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005454 first = false;
5455 break;
5456 }
5457 }
5458 i++;
5459 }
5460 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5461 if (str)
5462 free(str);
5463 str = str_parms_to_str(reply);
5464 }
5465
Alexy Joseph98988832017-01-13 14:56:59 -08005466 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5467 //only low latency track supports suspend_resume
5468 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005469 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005470 if (str)
5471 free(str);
5472 str = str_parms_to_str(reply);
5473 }
5474
5475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 str_parms_destroy(query);
5477 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005478 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005479 return str;
5480}
5481
5482static uint32_t out_get_latency(const struct audio_stream_out *stream)
5483{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005484 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005485 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005486 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005487
Alexy Josephaa54c872014-12-03 02:46:47 -08005488 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305489 lock_output_stream(out);
5490 latency = audio_extn_utils_compress_get_dsp_latency(out);
5491 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005492 } else if ((out->realtime) ||
5493 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005494 // since the buffer won't be filled up faster than realtime,
5495 // return a smaller number
5496 if (out->config.rate)
5497 period_ms = (out->af_period_multiplier * out->config.period_size *
5498 1000) / (out->config.rate);
5499 else
5500 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005501 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005502 } else {
5503 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005504 (out->config.rate);
5505 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)
5506 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005507 }
5508
Zhou Songd2537a02020-06-11 22:04:46 +08005509 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005510 latency += audio_extn_a2dp_get_encoder_latency();
5511
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305512 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005513 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514}
5515
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305516static float AmpToDb(float amplification)
5517{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305518 float db = DSD_VOLUME_MIN_DB;
5519 if (amplification > 0) {
5520 db = 20 * log10(amplification);
5521 if(db < DSD_VOLUME_MIN_DB)
5522 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305523 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305524 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305525}
5526
Arun Mirpuri5d170872019-03-26 13:21:31 -07005527static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5528 float right)
5529{
5530 struct stream_out *out = (struct stream_out *)stream;
5531 long volume = 0;
5532 char mixer_ctl_name[128] = "";
5533 struct audio_device *adev = out->dev;
5534 struct mixer_ctl *ctl = NULL;
5535 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5536 PCM_PLAYBACK);
5537
5538 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5539 "Playback %d Volume", pcm_device_id);
5540 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5541 if (!ctl) {
5542 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5543 __func__, mixer_ctl_name);
5544 return -EINVAL;
5545 }
5546 if (left != right)
5547 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5548 __func__, left, right);
5549 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5550 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5551 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5552 __func__, mixer_ctl_name, volume);
5553 return -EINVAL;
5554 }
5555 return 0;
5556}
5557
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305558static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5559 float right)
5560{
5561 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305562 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305563 char mixer_ctl_name[128];
5564 struct audio_device *adev = out->dev;
5565 struct mixer_ctl *ctl;
5566 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5567 PCM_PLAYBACK);
5568
5569 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5570 "Compress 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",
5574 __func__, mixer_ctl_name);
5575 return -EINVAL;
5576 }
5577 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5578 __func__, mixer_ctl_name, left, right);
5579 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5580 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5581 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5582
5583 return 0;
5584}
5585
Zhou Song2b8f28f2017-09-11 10:51:38 +08005586static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5587 float right)
5588{
5589 struct stream_out *out = (struct stream_out *)stream;
5590 char mixer_ctl_name[] = "App Type Gain";
5591 struct audio_device *adev = out->dev;
5592 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305593 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005594
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005595 if (!is_valid_volume(left, right)) {
5596 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5597 __func__, left, right);
5598 return -EINVAL;
5599 }
5600
Zhou Song2b8f28f2017-09-11 10:51:38 +08005601 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5602 if (!ctl) {
5603 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5604 __func__, mixer_ctl_name);
5605 return -EINVAL;
5606 }
5607
5608 set_values[0] = 0; //0: Rx Session 1:Tx Session
5609 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305610 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5611 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005612
5613 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5614 return 0;
5615}
5616
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305617static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5618 float right)
5619{
5620 struct stream_out *out = (struct stream_out *)stream;
5621 /* Volume control for pcm playback */
5622 if (left != right) {
5623 return -EINVAL;
5624 } else {
5625 char mixer_ctl_name[128];
5626 struct audio_device *adev = out->dev;
5627 struct mixer_ctl *ctl;
5628 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5629 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5630 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5631 if (!ctl) {
5632 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5633 return -EINVAL;
5634 }
5635
5636 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5637 int ret = mixer_ctl_set_value(ctl, 0, volume);
5638 if (ret < 0) {
5639 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5640 return -EINVAL;
5641 }
5642
5643 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5644
5645 return 0;
5646 }
5647}
5648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005649static int out_set_volume(struct audio_stream_out *stream, float left,
5650 float right)
5651{
Eric Laurenta9024de2013-04-04 09:19:12 -07005652 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005653 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305654 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005655
Arun Mirpuri5d170872019-03-26 13:21:31 -07005656 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005657 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5658 /* only take left channel into account: the API is for stereo anyway */
5659 out->muted = (left == 0.0f);
5660 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005661 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305662 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005663 /*
5664 * Set mute or umute on HDMI passthrough stream.
5665 * Only take left channel into account.
5666 * Mute is 0 and unmute 1
5667 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305668 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305669 } else if (out->format == AUDIO_FORMAT_DSD){
5670 char mixer_ctl_name[128] = "DSD Volume";
5671 struct audio_device *adev = out->dev;
5672 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5673
5674 if (!ctl) {
5675 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5676 __func__, mixer_ctl_name);
5677 return -EINVAL;
5678 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305679 volume[0] = (long)(AmpToDb(left));
5680 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305681 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5682 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005683 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005684 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005685 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5686 struct listnode *node = NULL;
5687 list_for_each(node, &adev->active_outputs_list) {
5688 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5689 streams_output_ctxt_t,
5690 list);
5691 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5692 out->volume_l = out_ctxt->output->volume_l;
5693 out->volume_r = out_ctxt->output->volume_r;
5694 }
5695 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005696 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005697 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005698 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5699 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005700 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005701 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005702 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005703 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005704 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5705 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305706 ret = out_set_compr_volume(stream, left, right);
5707 out->volume_l = left;
5708 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005709 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305710 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005711 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005712 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005713 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5714 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005715 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005716 if (!out->standby) {
5717 audio_extn_utils_send_app_type_gain(out->dev,
5718 out->app_type_cfg.app_type,
5719 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005720 if (!out->a2dp_muted)
5721 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005722 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005723 out->volume_l = left;
5724 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005725 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005726 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005727 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5728 ALOGV("%s: MMAP set volume called", __func__);
5729 if (!out->standby)
5730 ret = out_set_mmap_volume(stream, left, right);
5731 out->volume_l = left;
5732 out->volume_r = right;
5733 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305734 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305735 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5736 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005737 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305738 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005739 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305740 ret = out_set_pcm_volume(stream, left, right);
5741 else
5742 out->apply_volume = true;
5743
5744 out->volume_l = left;
5745 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005746 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305747 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005748 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5749 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005750 pthread_mutex_lock(&out->latch_lock);
5751 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005752 ret = out_set_pcm_volume(stream, left, right);
5753 out->volume_l = left;
5754 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005755 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005756 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005757 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 return -ENOSYS;
5760}
5761
Zhou Songc9672822017-08-16 16:01:39 +08005762static void update_frames_written(struct stream_out *out, size_t bytes)
5763{
5764 size_t bpf = 0;
5765
5766 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5767 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5768 bpf = 1;
5769 else if (!is_offload_usecase(out->usecase))
5770 bpf = audio_bytes_per_sample(out->format) *
5771 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005772
5773 pthread_mutex_lock(&out->position_query_lock);
5774 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005775 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005776 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5777 }
5778 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005779}
5780
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005781int split_and_write_audio_haptic_data(struct stream_out *out,
5782 const void *buffer, size_t bytes_to_write)
5783{
5784 struct audio_device *adev = out->dev;
5785
5786 int ret = 0;
5787 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5788 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5789 size_t frame_size = channel_count * bytes_per_sample;
5790 size_t frame_count = bytes_to_write / frame_size;
5791
5792 bool force_haptic_path =
5793 property_get_bool("vendor.audio.test_haptic", false);
5794
5795 // extract Haptics data from Audio buffer
5796 bool alloc_haptic_buffer = false;
5797 int haptic_channel_count = adev->haptics_config.channels;
5798 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5799 size_t audio_frame_size = frame_size - haptic_frame_size;
5800 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5801
5802 if (adev->haptic_buffer == NULL) {
5803 alloc_haptic_buffer = true;
5804 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5805 free(adev->haptic_buffer);
5806 adev->haptic_buffer_size = 0;
5807 alloc_haptic_buffer = true;
5808 }
5809
5810 if (alloc_haptic_buffer) {
5811 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005812 if(adev->haptic_buffer == NULL) {
5813 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5814 return -ENOMEM;
5815 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005816 adev->haptic_buffer_size = total_haptic_buffer_size;
5817 }
5818
5819 size_t src_index = 0, aud_index = 0, hap_index = 0;
5820 uint8_t *audio_buffer = (uint8_t *)buffer;
5821 uint8_t *haptic_buffer = adev->haptic_buffer;
5822
5823 // This is required for testing only. This works for stereo data only.
5824 // One channel is fed to audio stream and other to haptic stream for testing.
5825 if (force_haptic_path)
5826 audio_frame_size = haptic_frame_size = bytes_per_sample;
5827
5828 for (size_t i = 0; i < frame_count; i++) {
5829 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5830 audio_frame_size);
5831 aud_index += audio_frame_size;
5832 src_index += audio_frame_size;
5833
5834 if (adev->haptic_pcm)
5835 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5836 haptic_frame_size);
5837 hap_index += haptic_frame_size;
5838 src_index += haptic_frame_size;
5839
5840 // This is required for testing only.
5841 // Discard haptic channel data.
5842 if (force_haptic_path)
5843 src_index += haptic_frame_size;
5844 }
5845
5846 // write to audio pipeline
5847 ret = pcm_write(out->pcm, (void *)audio_buffer,
5848 frame_count * audio_frame_size);
5849
5850 // write to haptics pipeline
5851 if (adev->haptic_pcm)
5852 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5853 frame_count * haptic_frame_size);
5854
5855 return ret;
5856}
5857
Aalique Grahame22e49102018-12-18 14:23:57 -08005858#ifdef NO_AUDIO_OUT
5859static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5860 const void *buffer __unused, size_t bytes)
5861{
5862 struct stream_out *out = (struct stream_out *)stream;
5863
5864 /* No Output device supported other than BT for playback.
5865 * Sleep for the amount of buffer duration
5866 */
5867 lock_output_stream(out);
5868 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5869 (const struct audio_stream_out *)&out->stream) /
5870 out_get_sample_rate(&out->stream.common));
5871 pthread_mutex_unlock(&out->lock);
5872 return bytes;
5873}
5874#endif
5875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005876static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5877 size_t bytes)
5878{
5879 struct stream_out *out = (struct stream_out *)stream;
5880 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005881 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305882 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005883 const size_t frame_size = audio_stream_out_frame_size(stream);
5884 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305885 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005886 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887
Haynes Mathew George380745d2017-10-04 15:27:45 -07005888 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005889 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305890
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305891 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005892
Dhananjay Kumarac341582017-02-23 23:42:25 +05305893 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305894 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305895 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5896 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005897 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305898 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305899 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305900 ALOGD(" %s: sound card is not active/SSR state", __func__);
5901 ret= -EIO;
5902 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305903 }
5904 }
5905
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305906 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305907 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305908 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305909 goto exit;
5910 }
5911
Haynes Mathew George16081042017-05-31 17:16:49 -07005912 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5913 ret = -EINVAL;
5914 goto exit;
5915 }
5916
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005917 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305918 !out->is_iec61937_info_available) {
5919
5920 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5921 out->is_iec61937_info_available = true;
5922 } else if (audio_extn_passthru_is_enabled()) {
5923 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305924 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305925
5926 if((out->format == AUDIO_FORMAT_DTS) ||
5927 (out->format == AUDIO_FORMAT_DTS_HD)) {
5928 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5929 buffer, bytes);
5930 if (ret) {
5931 if (ret != -ENOSYS) {
5932 out->is_iec61937_info_available = false;
5933 ALOGD("iec61937 transmission info not yet updated retry");
5934 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305935 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305936 /* if stream has started and after that there is
5937 * stream config change (iec transmission config)
5938 * then trigger select_device to update backend configuration.
5939 */
5940 out->stream_config_changed = true;
5941 pthread_mutex_lock(&adev->lock);
5942 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305943 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005944 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305945 ret = -EINVAL;
5946 goto exit;
5947 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305948 pthread_mutex_unlock(&adev->lock);
5949 out->stream_config_changed = false;
5950 out->is_iec61937_info_available = true;
5951 }
5952 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305953
Meng Wang4c32fb42020-01-16 17:57:11 +08005954#ifdef AUDIO_GKI_ENABLED
5955 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5956 compr_passthr = out->compr_config.codec->reserved[0];
5957#else
5958 compr_passthr = out->compr_config.codec->compr_passthr;
5959#endif
5960
Garmond Leung317cbf12017-09-13 16:20:50 -07005961 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005962 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305963 (out->is_iec61937_info_available == true)) {
5964 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5965 ret = -EINVAL;
5966 goto exit;
5967 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305968 }
5969 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305970
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005971 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005972 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005973 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5974 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005975 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305976 ret = -EIO;
5977 goto exit;
5978 }
5979 }
5980 }
5981
Weiyin Jiangabedea32020-12-09 12:49:19 +08005982 if (is_usb_out_device_type(&out->device_list) &&
5983 !audio_extn_usb_connected(NULL)) {
5984 ret = -EIO;
5985 goto exit;
5986 }
5987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005988 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005989 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005990 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5991
Eric Laurent150dbfe2013-02-27 14:31:02 -08005992 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005993 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5994 ret = voice_extn_compress_voip_start_output_stream(out);
5995 else
5996 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005997 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005998 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005999 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006000 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006001 goto exit;
6002 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306003 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006004 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006005
6006 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006007 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006008 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306009 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006010 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006011 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306012
6013 if ((out->is_iec61937_info_available == true) &&
6014 (audio_extn_passthru_is_passthrough_stream(out))&&
6015 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6016 ret = -EINVAL;
6017 goto exit;
6018 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306019 if (out->set_dual_mono)
6020 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006021
6022 // log startup time in ms.
6023 simple_stats_log(
6024 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006026
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006027 if (adev->is_channel_status_set == false &&
6028 compare_device_type(&out->device_list,
6029 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006030 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306031 adev->is_channel_status_set = true;
6032 }
6033
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306034 if ((adev->use_old_pspd_mix_ctrl == true) &&
6035 (out->pspd_coeff_sent == false)) {
6036 /*
6037 * Need to resend pspd coefficients after stream started for
6038 * older kernel version as it does not save the coefficients
6039 * and also stream has to be started for coeff to apply.
6040 */
6041 usecase = get_usecase_from_list(adev, out->usecase);
6042 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306043 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306044 out->pspd_coeff_sent = true;
6045 }
6046 }
6047
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006048 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006049 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006050 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006051 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006052 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6053 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306054 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6055 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006056 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306057 out->send_next_track_params = false;
6058 out->is_compr_metadata_avail = false;
6059 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006060 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306061 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306062 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006063
Ashish Jain83a6cc22016-06-28 14:34:17 +05306064 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306065 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306066 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306067 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006068 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306069 return -EINVAL;
6070 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306071 audio_format_t dst_format = out->hal_op_format;
6072 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306073
Dieter Luecking5d57def2018-09-07 14:23:37 +02006074 /* prevent division-by-zero */
6075 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6076 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6077 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6078 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306079 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006080 ATRACE_END();
6081 return -EINVAL;
6082 }
6083
Ashish Jainf1eaa582016-05-23 20:54:24 +05306084 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6085 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6086
Ashish Jain83a6cc22016-06-28 14:34:17 +05306087 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306088 dst_format,
6089 buffer,
6090 src_format,
6091 frames);
6092
Ashish Jain83a6cc22016-06-28 14:34:17 +05306093 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306094 bytes_to_write);
6095
6096 /*Convert written bytes in audio flinger format*/
6097 if (ret > 0)
6098 ret = ((ret * format_to_bitwidth_table[out->format]) /
6099 format_to_bitwidth_table[dst_format]);
6100 }
6101 } else
6102 ret = compress_write(out->compr, buffer, bytes);
6103
Zhou Songc9672822017-08-16 16:01:39 +08006104 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6105 update_frames_written(out, bytes);
6106
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306107 if (ret < 0)
6108 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006109 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306110 /*msg to cb thread only if non blocking write is enabled*/
6111 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306112 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006113 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306114 } else if (-ENETRESET == ret) {
6115 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306116 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306117 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306118 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006119 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306120 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006121 }
Ashish Jain5106d362016-05-11 19:23:33 +05306122
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306123 /* Call compr start only when non-zero bytes of data is there to be rendered */
6124 if (!out->playback_started && ret > 0) {
6125 int status = compress_start(out->compr);
6126 if (status < 0) {
6127 ret = status;
6128 ALOGE("%s: compr start failed with err %d", __func__, errno);
6129 goto exit;
6130 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006131 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006132 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006133 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006134 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006135 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006136
6137 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6138 popcount(out->channel_mask),
6139 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006140 }
6141 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006142 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006143 return ret;
6144 } else {
6145 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006146 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006147 if (out->muted)
6148 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006149 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6150 __func__, frames, frame_size, bytes_to_write);
6151
Aalique Grahame22e49102018-12-18 14:23:57 -08006152 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006153 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6154 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6155 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006156 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6157 int16_t *src = (int16_t *)buffer;
6158 int16_t *dst = (int16_t *)buffer;
6159
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006160 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006161 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006162 "out_write called for %s use case with wrong properties",
6163 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006164
6165 /*
6166 * FIXME: this can be removed once audio flinger mixer supports
6167 * mono output
6168 */
6169
6170 /*
6171 * Code below goes over each frame in the buffer and adds both
6172 * L and R samples and then divides by 2 to convert to mono
6173 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006174 if (channel_count == 2) {
6175 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6176 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6177 }
6178 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006179 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006180 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006181
6182 // Note: since out_get_presentation_position() is called alternating with out_write()
6183 // by AudioFlinger, we can check underruns using the prior timestamp read.
6184 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6185 if (out->last_fifo_valid) {
6186 // compute drain to see if there is an underrun.
6187 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306188 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6189 int64_t frames_by_time =
6190 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6191 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006192 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6193
6194 if (underrun > 0) {
6195 simple_stats_log(&out->fifo_underruns, underrun);
6196
6197 ALOGW("%s: underrun(%lld) "
6198 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6199 __func__,
6200 (long long)out->fifo_underruns.n,
6201 (long long)frames_by_time,
6202 (long long)out->last_fifo_frames_remaining);
6203 }
6204 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6205 }
6206
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306207 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006208
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006209 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006210
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006211 if (out->config.rate)
6212 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6213 out->config.rate;
6214
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006215 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006216 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6217
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006218 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006219 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006220 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306221 out->convert_buffer != NULL) {
6222
6223 memcpy_by_audio_format(out->convert_buffer,
6224 out->hal_op_format,
6225 buffer,
6226 out->hal_ip_format,
6227 out->config.period_size * out->config.channels);
6228
6229 ret = pcm_write(out->pcm, out->convert_buffer,
6230 (out->config.period_size *
6231 out->config.channels *
6232 format_to_bitwidth_table[out->hal_op_format]));
6233 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306234 /*
6235 * To avoid underrun in DSP when the application is not pumping
6236 * data at required rate, check for the no. of bytes and ignore
6237 * pcm_write if it is less than actual buffer size.
6238 * It is a work around to a change in compress VOIP driver.
6239 */
6240 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6241 bytes < (out->config.period_size * out->config.channels *
6242 audio_bytes_per_sample(out->format))) {
6243 size_t voip_buf_size =
6244 out->config.period_size * out->config.channels *
6245 audio_bytes_per_sample(out->format);
6246 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6247 __func__, bytes, voip_buf_size);
6248 usleep(((uint64_t)voip_buf_size - bytes) *
6249 1000000 / audio_stream_out_frame_size(stream) /
6250 out_get_sample_rate(&out->stream.common));
6251 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006252 } else {
6253 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6254 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6255 else
6256 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6257 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306258 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006259
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006260 release_out_focus(out);
6261
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306262 if (ret < 0)
6263 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006264 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306265 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006267 }
6268
6269exit:
Zhou Songc9672822017-08-16 16:01:39 +08006270 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306271 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306272 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274 pthread_mutex_unlock(&out->lock);
6275
6276 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006277 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006278 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306279 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306280 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306281 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306282 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306283 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306284 out->standby = true;
6285 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306286 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006287 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6288 /* prevent division-by-zero */
6289 uint32_t stream_size = audio_stream_out_frame_size(stream);
6290 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006291
Dieter Luecking5d57def2018-09-07 14:23:37 +02006292 if ((stream_size == 0) || (srate == 0)) {
6293 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6294 ATRACE_END();
6295 return -EINVAL;
6296 }
6297 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6298 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006299 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306300 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006301 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006302 return ret;
6303 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006304 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006305 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006306 return bytes;
6307}
6308
6309static int out_get_render_position(const struct audio_stream_out *stream,
6310 uint32_t *dsp_frames)
6311{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006312 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006313
6314 if (dsp_frames == NULL)
6315 return -EINVAL;
6316
6317 *dsp_frames = 0;
6318 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006319 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306320
6321 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6322 * this operation and adev_close_output_stream(where out gets reset).
6323 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306324 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006325 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306326 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006327 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306328 return 0;
6329 }
6330
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006331 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306332 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306333 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006334 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306335 if (ret < 0)
6336 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006337 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306338 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006339 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306340 if (-ENETRESET == ret) {
6341 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306342 out->card_status = CARD_STATUS_OFFLINE;
6343 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306344 } else if(ret < 0) {
6345 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306346 ret = -EINVAL;
6347 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306348 /*
6349 * Handle corner case where compress session is closed during SSR
6350 * and timestamp is queried
6351 */
6352 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306353 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306354 } else if (out->prev_card_status_offline) {
6355 ALOGE("ERROR: previously sound card was offline,return error");
6356 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306357 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306358 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006359 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306360 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306361 pthread_mutex_unlock(&out->lock);
6362 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006363 } else if (audio_is_linear_pcm(out->format)) {
6364 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006365 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006366 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006367 } else
6368 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006369}
6370
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006371static int out_add_audio_effect(const struct audio_stream *stream __unused,
6372 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006373{
6374 return 0;
6375}
6376
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006377static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6378 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006379{
6380 return 0;
6381}
6382
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006383static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6384 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006385{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306386 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006387}
6388
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006389static int out_get_presentation_position(const struct audio_stream_out *stream,
6390 uint64_t *frames, struct timespec *timestamp)
6391{
6392 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306393 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006394 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006395
Ashish Jain5106d362016-05-11 19:23:33 +05306396 /* below piece of code is not guarded against any lock because audioFliner serializes
6397 * this operation and adev_close_output_stream( where out gets reset).
6398 */
6399 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306400 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006401 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306402 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6403 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6404 return 0;
6405 }
6406
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006407 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006408
Ashish Jain5106d362016-05-11 19:23:33 +05306409 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6410 ret = compress_get_tstamp(out->compr, &dsp_frames,
6411 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006412 // Adjustment accounts for A2dp encoder latency with offload usecases
6413 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006414 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006415 unsigned long offset =
6416 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6417 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6418 }
Ashish Jain5106d362016-05-11 19:23:33 +05306419 ALOGVV("%s rendered frames %ld sample_rate %d",
6420 __func__, dsp_frames, out->sample_rate);
6421 *frames = dsp_frames;
6422 if (ret < 0)
6423 ret = -errno;
6424 if (-ENETRESET == ret) {
6425 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306426 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306427 ret = -EINVAL;
6428 } else
6429 ret = 0;
6430 /* this is the best we can do */
6431 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006432 } else {
6433 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006434 unsigned int avail;
6435 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006436 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006437 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006438
Andy Hunga1f48fa2019-07-01 18:14:53 -07006439 if (out->kernel_buffer_size > avail) {
6440 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6441 } else {
6442 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6443 __func__, avail, out->kernel_buffer_size);
6444 avail = out->kernel_buffer_size;
6445 frames_temp = out->last_fifo_frames_remaining = 0;
6446 }
6447 out->last_fifo_valid = true;
6448 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6449
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006450 if (out->written >= frames_temp)
6451 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006452
Andy Hunga1f48fa2019-07-01 18:14:53 -07006453 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6454 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6455
Weiyin Jiangd4633762018-03-16 12:05:03 +08006456 // This adjustment accounts for buffering after app processor.
6457 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006458 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006459 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006460 if (signed_frames >= frames_temp)
6461 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006462
Weiyin Jiangd4633762018-03-16 12:05:03 +08006463 // Adjustment accounts for A2dp encoder latency with non offload usecases
6464 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006465 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006466 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6467 if (signed_frames >= frames_temp)
6468 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006469 }
6470
6471 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006472 *frames = signed_frames;
6473 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006474 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006475 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6476 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006477 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306478 *frames = out->written;
6479 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306480 if (is_offload_usecase(out->usecase))
6481 ret = -EINVAL;
6482 else
6483 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006484 }
6485 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006486 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006487 return ret;
6488}
6489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006490static int out_set_callback(struct audio_stream_out *stream,
6491 stream_callback_t callback, void *cookie)
6492{
6493 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006494 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006495
6496 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006497 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006498 out->client_callback = callback;
6499 out->client_cookie = cookie;
6500 if (out->adsp_hdlr_stream_handle) {
6501 ret = audio_extn_adsp_hdlr_stream_set_callback(
6502 out->adsp_hdlr_stream_handle,
6503 callback,
6504 cookie);
6505 if (ret)
6506 ALOGW("%s:adsp hdlr callback registration failed %d",
6507 __func__, ret);
6508 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006509 pthread_mutex_unlock(&out->lock);
6510 return 0;
6511}
6512
6513static int out_pause(struct audio_stream_out* stream)
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)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006519 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306520 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006521 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006522 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006523 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306524 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306525 status = compress_pause(out->compr);
6526
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006527 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006528
Mingming Yin21854652016-04-13 11:54:02 -07006529 if (audio_extn_passthru_is_active()) {
6530 ALOGV("offload use case, pause passthru");
6531 audio_extn_passthru_on_pause(out);
6532 }
6533
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306534 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006535 audio_extn_dts_notify_playback_state(out->usecase, 0,
6536 out->sample_rate, popcount(out->channel_mask),
6537 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006538 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006539 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006540 pthread_mutex_unlock(&out->lock);
6541 }
6542 return status;
6543}
6544
6545static int out_resume(struct audio_stream_out* stream)
6546{
6547 struct stream_out *out = (struct stream_out *)stream;
6548 int status = -ENOSYS;
6549 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006550 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006551 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306552 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006553 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006554 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006555 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306556 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306557 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006558 }
6559 if (!status) {
6560 out->offload_state = OFFLOAD_STATE_PLAYING;
6561 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306562 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006563 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6564 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006565 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006566 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006567 pthread_mutex_unlock(&out->lock);
6568 }
6569 return status;
6570}
6571
6572static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6573{
6574 struct stream_out *out = (struct stream_out *)stream;
6575 int status = -ENOSYS;
6576 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006577 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006578 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006579 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6580 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6581 else
6582 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6583 pthread_mutex_unlock(&out->lock);
6584 }
6585 return status;
6586}
6587
6588static int out_flush(struct audio_stream_out* stream)
6589{
6590 struct stream_out *out = (struct stream_out *)stream;
6591 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006592 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006593 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006594 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006595 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006596 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306597 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006598 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006599 } else {
6600 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306601 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006602 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006603 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006604 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006605 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006606 return 0;
6607 }
6608 return -ENOSYS;
6609}
6610
Haynes Mathew George16081042017-05-31 17:16:49 -07006611static int out_stop(const struct audio_stream_out* stream)
6612{
6613 struct stream_out *out = (struct stream_out *)stream;
6614 struct audio_device *adev = out->dev;
6615 int ret = -ENOSYS;
6616
6617 ALOGV("%s", __func__);
6618 pthread_mutex_lock(&adev->lock);
6619 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6620 out->playback_started && out->pcm != NULL) {
6621 pcm_stop(out->pcm);
6622 ret = stop_output_stream(out);
6623 out->playback_started = false;
6624 }
6625 pthread_mutex_unlock(&adev->lock);
6626 return ret;
6627}
6628
6629static int out_start(const struct audio_stream_out* stream)
6630{
6631 struct stream_out *out = (struct stream_out *)stream;
6632 struct audio_device *adev = out->dev;
6633 int ret = -ENOSYS;
6634
6635 ALOGV("%s", __func__);
6636 pthread_mutex_lock(&adev->lock);
6637 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6638 !out->playback_started && out->pcm != NULL) {
6639 ret = start_output_stream(out);
6640 if (ret == 0) {
6641 out->playback_started = true;
6642 }
6643 }
6644 pthread_mutex_unlock(&adev->lock);
6645 return ret;
6646}
6647
6648/*
6649 * Modify config->period_count based on min_size_frames
6650 */
6651static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6652{
6653 int periodCountRequested = (min_size_frames + config->period_size - 1)
6654 / config->period_size;
6655 int periodCount = MMAP_PERIOD_COUNT_MIN;
6656
6657 ALOGV("%s original config.period_size = %d config.period_count = %d",
6658 __func__, config->period_size, config->period_count);
6659
6660 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6661 periodCount *= 2;
6662 }
6663 config->period_count = periodCount;
6664
6665 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6666}
6667
Phil Burkfe17efd2019-03-25 10:23:35 -07006668// Read offset for the positional timestamp from a persistent vendor property.
6669// This is to workaround apparent inaccuracies in the timing information that
6670// is used by the AAudio timing model. The inaccuracies can cause glitches.
6671static int64_t get_mmap_out_time_offset() {
6672 const int32_t kDefaultOffsetMicros = 0;
6673 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006674 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006675 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6676 return mmap_time_offset_micros * (int64_t)1000;
6677}
6678
Haynes Mathew George16081042017-05-31 17:16:49 -07006679static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6680 int32_t min_size_frames,
6681 struct audio_mmap_buffer_info *info)
6682{
6683 struct stream_out *out = (struct stream_out *)stream;
6684 struct audio_device *adev = out->dev;
6685 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006686 unsigned int offset1 = 0;
6687 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006688 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006689 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006690 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006691
Arun Mirpuri5d170872019-03-26 13:21:31 -07006692 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306693 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006694 pthread_mutex_lock(&adev->lock);
6695
Sharad Sanglec6f32552018-05-04 16:15:38 +05306696 if (CARD_STATUS_OFFLINE == out->card_status ||
6697 CARD_STATUS_OFFLINE == adev->card_status) {
6698 ALOGW("out->card_status or adev->card_status offline, try again");
6699 ret = -EIO;
6700 goto exit;
6701 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306702 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006703 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6704 ret = -EINVAL;
6705 goto exit;
6706 }
6707 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6708 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6709 ret = -ENOSYS;
6710 goto exit;
6711 }
6712 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6713 if (out->pcm_device_id < 0) {
6714 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6715 __func__, out->pcm_device_id, out->usecase);
6716 ret = -EINVAL;
6717 goto exit;
6718 }
6719
6720 adjust_mmap_period_count(&out->config, min_size_frames);
6721
Arun Mirpuri5d170872019-03-26 13:21:31 -07006722 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006723 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6724 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6725 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306726 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306727 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6728 out->card_status = CARD_STATUS_OFFLINE;
6729 adev->card_status = CARD_STATUS_OFFLINE;
6730 ret = -EIO;
6731 goto exit;
6732 }
6733
Haynes Mathew George16081042017-05-31 17:16:49 -07006734 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6735 step = "open";
6736 ret = -ENODEV;
6737 goto exit;
6738 }
6739 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6740 if (ret < 0) {
6741 step = "begin";
6742 goto exit;
6743 }
juyuchen626833d2019-06-04 16:48:02 +08006744
6745 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006746 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006747 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006748 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006749 ret = platform_get_mmap_data_fd(adev->platform,
6750 out->pcm_device_id, 0 /*playback*/,
6751 &info->shared_memory_fd,
6752 &mmap_size);
6753 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006754 // Fall back to non exclusive mode
6755 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6756 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006757 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6758 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6759
Arun Mirpuri5d170872019-03-26 13:21:31 -07006760 if (mmap_size < buffer_size) {
6761 step = "mmap";
6762 goto exit;
6763 }
juyuchen626833d2019-06-04 16:48:02 +08006764 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006765 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006766 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006767 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006768
6769 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6770 if (ret < 0) {
6771 step = "commit";
6772 goto exit;
6773 }
6774
Phil Burkfe17efd2019-03-25 10:23:35 -07006775 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6776
Haynes Mathew George16081042017-05-31 17:16:49 -07006777 out->standby = false;
6778 ret = 0;
6779
Arun Mirpuri5d170872019-03-26 13:21:31 -07006780 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006781 __func__, info->shared_memory_address, info->buffer_size_frames);
6782
6783exit:
6784 if (ret != 0) {
6785 if (out->pcm == NULL) {
6786 ALOGE("%s: %s - %d", __func__, step, ret);
6787 } else {
6788 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6789 pcm_close(out->pcm);
6790 out->pcm = NULL;
6791 }
6792 }
6793 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306794 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006795 return ret;
6796}
6797
6798static int out_get_mmap_position(const struct audio_stream_out *stream,
6799 struct audio_mmap_position *position)
6800{
6801 struct stream_out *out = (struct stream_out *)stream;
6802 ALOGVV("%s", __func__);
6803 if (position == NULL) {
6804 return -EINVAL;
6805 }
6806 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006807 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006808 return -ENOSYS;
6809 }
6810 if (out->pcm == NULL) {
6811 return -ENOSYS;
6812 }
6813
6814 struct timespec ts = { 0, 0 };
6815 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6816 if (ret < 0) {
6817 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6818 return ret;
6819 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006820 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6821 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006822 return 0;
6823}
6824
6825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006826/** audio_stream_in implementation **/
6827static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6828{
6829 struct stream_in *in = (struct stream_in *)stream;
6830
6831 return in->config.rate;
6832}
6833
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006834static int in_set_sample_rate(struct audio_stream *stream __unused,
6835 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836{
6837 return -ENOSYS;
6838}
6839
6840static size_t in_get_buffer_size(const struct audio_stream *stream)
6841{
6842 struct stream_in *in = (struct stream_in *)stream;
6843
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006844 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6845 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006846 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6847 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306848 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306849 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006850
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006851 return in->config.period_size * in->af_period_multiplier *
6852 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006853}
6854
6855static uint32_t in_get_channels(const struct audio_stream *stream)
6856{
6857 struct stream_in *in = (struct stream_in *)stream;
6858
6859 return in->channel_mask;
6860}
6861
6862static audio_format_t in_get_format(const struct audio_stream *stream)
6863{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006864 struct stream_in *in = (struct stream_in *)stream;
6865
6866 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006867}
6868
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006869static int in_set_format(struct audio_stream *stream __unused,
6870 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006871{
6872 return -ENOSYS;
6873}
6874
6875static int in_standby(struct audio_stream *stream)
6876{
6877 struct stream_in *in = (struct stream_in *)stream;
6878 struct audio_device *adev = in->dev;
6879 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306880 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6881 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006882 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306883
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006884 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006885 if (!in->standby && in->is_st_session) {
6886 ALOGD("%s: sound trigger pcm stop lab", __func__);
6887 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006888 if (adev->num_va_sessions > 0)
6889 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006890 in->standby = 1;
6891 }
6892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006893 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006894 if (adev->adm_deregister_stream)
6895 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6896
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006897 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006898 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006899 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006900 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006901 voice_extn_compress_voip_close_input_stream(stream);
6902 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006903 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6904 do_stop = in->capture_started;
6905 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006906 if (in->mmap_shared_memory_fd >= 0) {
6907 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6908 __func__, in->mmap_shared_memory_fd);
6909 close(in->mmap_shared_memory_fd);
6910 in->mmap_shared_memory_fd = -1;
6911 }
Zhou Songa8895042016-07-05 17:54:22 +08006912 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306913 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306914 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006915 }
6916
Arun Mirpuri5d170872019-03-26 13:21:31 -07006917 if (in->pcm) {
6918 ATRACE_BEGIN("pcm_in_close");
6919 pcm_close(in->pcm);
6920 ATRACE_END();
6921 in->pcm = NULL;
6922 }
6923
Carter Hsu2e429db2019-05-14 18:50:52 +08006924 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006925 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006926
George Gao3018ede2019-10-23 13:23:00 -07006927 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6928 if (adev->num_va_sessions > 0)
6929 adev->num_va_sessions--;
6930 }
Quinn Malef6050362019-01-30 15:55:40 -08006931
Eric Laurent150dbfe2013-02-27 14:31:02 -08006932 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006933 }
6934 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006935 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006936 return status;
6937}
6938
Aalique Grahame22e49102018-12-18 14:23:57 -08006939static int in_dump(const struct audio_stream *stream,
6940 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006941{
Aalique Grahame22e49102018-12-18 14:23:57 -08006942 struct stream_in *in = (struct stream_in *)stream;
6943
6944 // We try to get the lock for consistency,
6945 // but it isn't necessary for these variables.
6946 // If we're not in standby, we may be blocked on a read.
6947 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6948 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6949 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6950 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6951
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006952 char buffer[256]; // for statistics formatting
6953 if (in->start_latency_ms.n > 0) {
6954 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6955 dprintf(fd, " Start latency ms: %s\n", buffer);
6956 }
6957
Aalique Grahame22e49102018-12-18 14:23:57 -08006958 if (locked) {
6959 pthread_mutex_unlock(&in->lock);
6960 }
6961
6962 // dump error info
6963 (void)error_log_dump(
6964 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006966 return 0;
6967}
6968
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306969static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6970{
6971 if (!stream || !parms)
6972 return;
6973
6974 struct stream_in *in = (struct stream_in *)stream;
6975 struct audio_device *adev = in->dev;
6976
6977 card_status_t status;
6978 int card;
6979 if (parse_snd_card_status(parms, &card, &status) < 0)
6980 return;
6981
6982 pthread_mutex_lock(&adev->lock);
6983 bool valid_cb = (card == adev->snd_card);
6984 pthread_mutex_unlock(&adev->lock);
6985
6986 if (!valid_cb)
6987 return;
6988
6989 lock_input_stream(in);
6990 if (in->card_status != status)
6991 in->card_status = status;
6992 pthread_mutex_unlock(&in->lock);
6993
6994 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6995 use_case_table[in->usecase],
6996 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6997
6998 // a better solution would be to report error back to AF and let
6999 // it put the stream to standby
7000 if (status == CARD_STATUS_OFFLINE)
7001 in_standby(&in->stream.common);
7002
7003 return;
7004}
7005
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007006int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007007 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007008 audio_source_t source)
7009{
7010 struct audio_device *adev = in->dev;
7011 int ret = 0;
7012
7013 lock_input_stream(in);
7014 pthread_mutex_lock(&adev->lock);
7015
7016 /* no audio source uses val == 0 */
7017 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7018 in->source = source;
7019 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7020 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7021 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7022 (in->config.rate == 8000 || in->config.rate == 16000 ||
7023 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7024 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7025 ret = voice_extn_compress_voip_open_input_stream(in);
7026 if (ret != 0) {
7027 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7028 __func__, ret);
7029 }
7030 }
7031 }
7032
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007033 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7034 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007035 // Workaround: If routing to an non existing usb device, fail gracefully
7036 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007037 struct str_parms *usb_addr =
7038 str_parms_create_str(get_usb_device_address(devices));
7039 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007040 !audio_extn_usb_connected(NULL)) {
7041 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007042 ret = -ENOSYS;
7043 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007044 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007045 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007046 if (!in->standby && !in->is_st_session) {
7047 ALOGV("update input routing change");
7048 // inform adm before actual routing to prevent glitches.
7049 if (adev->adm_on_routing_change) {
7050 adev->adm_on_routing_change(adev->adm_data,
7051 in->capture_handle);
7052 ret = select_devices(adev, in->usecase);
7053 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7054 adev->adm_routing_changed = true;
7055 }
7056 }
7057 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007058 if (usb_addr)
7059 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007060 }
7061 pthread_mutex_unlock(&adev->lock);
7062 pthread_mutex_unlock(&in->lock);
7063
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007064 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007065 return ret;
7066}
7067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007068static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7069{
7070 struct stream_in *in = (struct stream_in *)stream;
7071 struct audio_device *adev = in->dev;
7072 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007073 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307074 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007075
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307076 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007077 parms = str_parms_create_str(kvpairs);
7078
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307079 if (!parms)
7080 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007081 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007082 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007083
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307084 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7085 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307086 strlcpy(in->profile, value, sizeof(in->profile));
7087 ALOGV("updating stream profile with value '%s'", in->profile);
7088 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7089 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007090 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307091 in->sample_rate, in->bit_width,
7092 in->profile, &in->app_type_cfg);
7093 }
7094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007095 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007096 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007097
7098 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307099error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307100 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007101}
7102
7103static char* in_get_parameters(const struct audio_stream *stream,
7104 const char *keys)
7105{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007106 struct stream_in *in = (struct stream_in *)stream;
7107 struct str_parms *query = str_parms_create_str(keys);
7108 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007109 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007110
7111 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007112 if (reply) {
7113 str_parms_destroy(reply);
7114 }
7115 if (query) {
7116 str_parms_destroy(query);
7117 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007118 ALOGE("in_get_parameters: failed to create query or reply");
7119 return NULL;
7120 }
7121
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007122 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007123
7124 voice_extn_in_get_parameters(in, query, reply);
7125
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007126 stream_get_parameter_channels(query, reply,
7127 &in->supported_channel_masks[0]);
7128 stream_get_parameter_formats(query, reply,
7129 &in->supported_formats[0]);
7130 stream_get_parameter_rates(query, reply,
7131 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007132 str = str_parms_to_str(reply);
7133 str_parms_destroy(query);
7134 str_parms_destroy(reply);
7135
7136 ALOGV("%s: exit: returns - %s", __func__, str);
7137 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138}
7139
Aalique Grahame22e49102018-12-18 14:23:57 -08007140static int in_set_gain(struct audio_stream_in *stream,
7141 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142{
Aalique Grahame22e49102018-12-18 14:23:57 -08007143 struct stream_in *in = (struct stream_in *)stream;
7144 char mixer_ctl_name[128];
7145 struct mixer_ctl *ctl;
7146 int ctl_value;
7147
7148 ALOGV("%s: gain %f", __func__, gain);
7149
7150 if (stream == NULL)
7151 return -EINVAL;
7152
7153 /* in_set_gain() only used to silence MMAP capture for now */
7154 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7155 return -ENOSYS;
7156
7157 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7158
7159 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7160 if (!ctl) {
7161 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7162 __func__, mixer_ctl_name);
7163 return -ENOSYS;
7164 }
7165
7166 if (gain < RECORD_GAIN_MIN)
7167 gain = RECORD_GAIN_MIN;
7168 else if (gain > RECORD_GAIN_MAX)
7169 gain = RECORD_GAIN_MAX;
7170 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7171
7172 mixer_ctl_set_value(ctl, 0, ctl_value);
7173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007174 return 0;
7175}
7176
7177static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7178 size_t bytes)
7179{
7180 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307181
7182 if (in == NULL) {
7183 ALOGE("%s: stream_in ptr is NULL", __func__);
7184 return -EINVAL;
7185 }
7186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307188 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307189 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007190
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007191 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307192
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007193 if (in->is_st_session) {
7194 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7195 /* Read from sound trigger HAL */
7196 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007197 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007198 if (adev->num_va_sessions < UINT_MAX)
7199 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007200 in->standby = 0;
7201 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007202 pthread_mutex_unlock(&in->lock);
7203 return bytes;
7204 }
7205
Haynes Mathew George16081042017-05-31 17:16:49 -07007206 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7207 ret = -ENOSYS;
7208 goto exit;
7209 }
7210
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007211 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7212 !in->standby && adev->adm_routing_changed) {
7213 ret = -ENOSYS;
7214 goto exit;
7215 }
7216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007217 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007218 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7219
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007220 pthread_mutex_lock(&adev->lock);
7221 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7222 ret = voice_extn_compress_voip_start_input_stream(in);
7223 else
7224 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007225 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7226 if (adev->num_va_sessions < UINT_MAX)
7227 adev->num_va_sessions++;
7228 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007229 pthread_mutex_unlock(&adev->lock);
7230 if (ret != 0) {
7231 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007232 }
7233 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007234
7235 // log startup time in ms.
7236 simple_stats_log(
7237 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007238 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007239
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307240 /* Avoid read if capture_stopped is set */
7241 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7242 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7243 ret = -EINVAL;
7244 goto exit;
7245 }
7246
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007247 // what's the duration requested by the client?
7248 long ns = 0;
7249
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307250 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007251 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7252 in->config.rate;
7253
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007254 ret = request_in_focus(in, ns);
7255 if (ret != 0)
7256 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007257 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007258
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307259 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307260 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7261 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307262 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007263 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307264 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007265 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007266 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007267 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007268 } else if (audio_extn_ffv_get_stream() == in) {
7269 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307270 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007271 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307272 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7273 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7274 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7275 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307276 ret = -EINVAL;
7277 goto exit;
7278 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307279 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307280 ret = -errno;
7281 }
7282 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307283 /* bytes read is always set to bytes for non compress usecases */
7284 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007285 }
7286
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007287 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007289 /*
Quinn Malef6050362019-01-30 15:55:40 -08007290 * Instead of writing zeroes here, we could trust the hardware to always
7291 * provide zeroes when muted. This is also muted with voice recognition
7292 * usecases so that other clients do not have access to voice recognition
7293 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007294 */
Quinn Malef6050362019-01-30 15:55:40 -08007295 if ((ret == 0 && voice_get_mic_mute(adev) &&
7296 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007297 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7298 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007299 (adev->num_va_sessions &&
7300 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7301 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7302 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007303 memset(buffer, 0, bytes);
7304
7305exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307306 frame_size = audio_stream_in_frame_size(stream);
7307 if (frame_size > 0)
7308 in->frames_read += bytes_read/frame_size;
7309
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007310 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307311 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007312 pthread_mutex_unlock(&in->lock);
7313
7314 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307315 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307316 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307317 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307318 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307319 in->standby = true;
7320 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307321 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307322 bytes_read = bytes;
7323 memset(buffer, 0, bytes);
7324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007326 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7327 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007328 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307329 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307330 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007331 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307332 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333}
7334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007335static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007336{
7337 return 0;
7338}
7339
Aalique Grahame22e49102018-12-18 14:23:57 -08007340static int in_get_capture_position(const struct audio_stream_in *stream,
7341 int64_t *frames, int64_t *time)
7342{
7343 if (stream == NULL || frames == NULL || time == NULL) {
7344 return -EINVAL;
7345 }
7346 struct stream_in *in = (struct stream_in *)stream;
7347 int ret = -ENOSYS;
7348
7349 lock_input_stream(in);
7350 // note: ST sessions do not close the alsa pcm driver synchronously
7351 // on standby. Therefore, we may return an error even though the
7352 // pcm stream is still opened.
7353 if (in->standby) {
7354 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7355 "%s stream in standby but pcm not NULL for non ST session", __func__);
7356 goto exit;
7357 }
7358 if (in->pcm) {
7359 struct timespec timestamp;
7360 unsigned int avail;
7361 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7362 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007363 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007364 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307365 //Adjustment accounts for A2dp decoder latency for recording usecase
7366 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7367 if (is_a2dp_in_device_type(&in->device_list))
7368 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007369 ret = 0;
7370 }
7371 }
7372exit:
7373 pthread_mutex_unlock(&in->lock);
7374 return ret;
7375}
7376
Carter Hsu2e429db2019-05-14 18:50:52 +08007377static int in_update_effect_list(bool add, effect_handle_t effect,
7378 struct listnode *head)
7379{
7380 struct listnode *node;
7381 struct in_effect_list *elist = NULL;
7382 struct in_effect_list *target = NULL;
7383 int ret = 0;
7384
7385 if (!head)
7386 return ret;
7387
7388 list_for_each(node, head) {
7389 elist = node_to_item(node, struct in_effect_list, list);
7390 if (elist->handle == effect) {
7391 target = elist;
7392 break;
7393 }
7394 }
7395
7396 if (add) {
7397 if (target) {
7398 ALOGD("effect %p already exist", effect);
7399 return ret;
7400 }
7401
7402 target = (struct in_effect_list *)
7403 calloc(1, sizeof(struct in_effect_list));
7404
7405 if (!target) {
7406 ALOGE("%s:fail to allocate memory", __func__);
7407 return -ENOMEM;
7408 }
7409
7410 target->handle = effect;
7411 list_add_tail(head, &target->list);
7412 } else {
7413 if (target) {
7414 list_remove(&target->list);
7415 free(target);
7416 }
7417 }
7418
7419 return ret;
7420}
7421
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007422static int add_remove_audio_effect(const struct audio_stream *stream,
7423 effect_handle_t effect,
7424 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007425{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007426 struct stream_in *in = (struct stream_in *)stream;
7427 int status = 0;
7428 effect_descriptor_t desc;
7429
7430 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007431 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7432
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007433 if (status != 0)
7434 return status;
7435
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007436 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007437 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007438 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007439 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7440 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007441 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007442
7443 in_update_effect_list(enable, effect, &in->aec_list);
7444 enable = !list_empty(&in->aec_list);
7445 if (enable == in->enable_aec)
7446 goto exit;
7447
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007448 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007449 ALOGD("AEC enable %d", enable);
7450
Aalique Grahame22e49102018-12-18 14:23:57 -08007451 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7452 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7453 in->dev->enable_voicerx = enable;
7454 struct audio_usecase *usecase;
7455 struct listnode *node;
7456 list_for_each(node, &in->dev->usecase_list) {
7457 usecase = node_to_item(node, struct audio_usecase, list);
7458 if (usecase->type == PCM_PLAYBACK)
7459 select_devices(in->dev, usecase->id);
7460 }
7461 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007462 if (!in->standby) {
7463 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7464 select_devices(in->dev, in->usecase);
7465 }
7466
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007467 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007468 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7469
7470 in_update_effect_list(enable, effect, &in->ns_list);
7471 enable = !list_empty(&in->ns_list);
7472 if (enable == in->enable_ns)
7473 goto exit;
7474
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007475 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007476 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007477 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007478 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7479 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007480 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7481 select_devices(in->dev, in->usecase);
7482 } else
7483 select_devices(in->dev, in->usecase);
7484 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007485 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007486exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007487 pthread_mutex_unlock(&in->dev->lock);
7488 pthread_mutex_unlock(&in->lock);
7489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007490 return 0;
7491}
7492
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007493static int in_add_audio_effect(const struct audio_stream *stream,
7494 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007495{
Eric Laurent994a6932013-07-17 11:51:42 -07007496 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007497 return add_remove_audio_effect(stream, effect, true);
7498}
7499
7500static int in_remove_audio_effect(const struct audio_stream *stream,
7501 effect_handle_t effect)
7502{
Eric Laurent994a6932013-07-17 11:51:42 -07007503 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007504 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007505}
7506
Haynes Mathew George16081042017-05-31 17:16:49 -07007507static int in_stop(const struct audio_stream_in* stream)
7508{
7509 struct stream_in *in = (struct stream_in *)stream;
7510 struct audio_device *adev = in->dev;
7511
7512 int ret = -ENOSYS;
7513 ALOGV("%s", __func__);
7514 pthread_mutex_lock(&adev->lock);
7515 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7516 in->capture_started && in->pcm != NULL) {
7517 pcm_stop(in->pcm);
7518 ret = stop_input_stream(in);
7519 in->capture_started = false;
7520 }
7521 pthread_mutex_unlock(&adev->lock);
7522 return ret;
7523}
7524
7525static int in_start(const struct audio_stream_in* stream)
7526{
7527 struct stream_in *in = (struct stream_in *)stream;
7528 struct audio_device *adev = in->dev;
7529 int ret = -ENOSYS;
7530
7531 ALOGV("%s in %p", __func__, in);
7532 pthread_mutex_lock(&adev->lock);
7533 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7534 !in->capture_started && in->pcm != NULL) {
7535 if (!in->capture_started) {
7536 ret = start_input_stream(in);
7537 if (ret == 0) {
7538 in->capture_started = true;
7539 }
7540 }
7541 }
7542 pthread_mutex_unlock(&adev->lock);
7543 return ret;
7544}
7545
Phil Burke0a86d12019-02-16 22:28:11 -08007546// Read offset for the positional timestamp from a persistent vendor property.
7547// This is to workaround apparent inaccuracies in the timing information that
7548// is used by the AAudio timing model. The inaccuracies can cause glitches.
7549static int64_t in_get_mmap_time_offset() {
7550 const int32_t kDefaultOffsetMicros = 0;
7551 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007552 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007553 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7554 return mmap_time_offset_micros * (int64_t)1000;
7555}
7556
Haynes Mathew George16081042017-05-31 17:16:49 -07007557static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7558 int32_t min_size_frames,
7559 struct audio_mmap_buffer_info *info)
7560{
7561 struct stream_in *in = (struct stream_in *)stream;
7562 struct audio_device *adev = in->dev;
7563 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007564 unsigned int offset1 = 0;
7565 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007566 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007567 uint32_t mmap_size = 0;
7568 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007569
7570 pthread_mutex_lock(&adev->lock);
7571 ALOGV("%s in %p", __func__, in);
7572
Sharad Sanglec6f32552018-05-04 16:15:38 +05307573 if (CARD_STATUS_OFFLINE == in->card_status||
7574 CARD_STATUS_OFFLINE == adev->card_status) {
7575 ALOGW("in->card_status or adev->card_status offline, try again");
7576 ret = -EIO;
7577 goto exit;
7578 }
7579
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307580 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007581 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7582 ret = -EINVAL;
7583 goto exit;
7584 }
7585 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7586 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7587 ALOGV("%s in %p", __func__, in);
7588 ret = -ENOSYS;
7589 goto exit;
7590 }
7591 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7592 if (in->pcm_device_id < 0) {
7593 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7594 __func__, in->pcm_device_id, in->usecase);
7595 ret = -EINVAL;
7596 goto exit;
7597 }
7598
7599 adjust_mmap_period_count(&in->config, min_size_frames);
7600
7601 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7602 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7603 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7604 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307605 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307606 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7607 in->card_status = CARD_STATUS_OFFLINE;
7608 adev->card_status = CARD_STATUS_OFFLINE;
7609 ret = -EIO;
7610 goto exit;
7611 }
7612
Haynes Mathew George16081042017-05-31 17:16:49 -07007613 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7614 step = "open";
7615 ret = -ENODEV;
7616 goto exit;
7617 }
7618
7619 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7620 if (ret < 0) {
7621 step = "begin";
7622 goto exit;
7623 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007624
juyuchen626833d2019-06-04 16:48:02 +08007625 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007626 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7627 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7628 info->burst_size_frames = in->config.period_size;
7629 ret = platform_get_mmap_data_fd(adev->platform,
7630 in->pcm_device_id, 1 /*capture*/,
7631 &info->shared_memory_fd,
7632 &mmap_size);
7633 if (ret < 0) {
7634 // Fall back to non exclusive mode
7635 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7636 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007637 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7638 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7639
Arun Mirpuri5d170872019-03-26 13:21:31 -07007640 if (mmap_size < buffer_size) {
7641 step = "mmap";
7642 goto exit;
7643 }
juyuchen626833d2019-06-04 16:48:02 +08007644 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007645 }
7646
7647 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007648
7649 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7650 if (ret < 0) {
7651 step = "commit";
7652 goto exit;
7653 }
7654
Phil Burke0a86d12019-02-16 22:28:11 -08007655 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7656
Haynes Mathew George16081042017-05-31 17:16:49 -07007657 in->standby = false;
7658 ret = 0;
7659
7660 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7661 __func__, info->shared_memory_address, info->buffer_size_frames);
7662
7663exit:
7664 if (ret != 0) {
7665 if (in->pcm == NULL) {
7666 ALOGE("%s: %s - %d", __func__, step, ret);
7667 } else {
7668 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7669 pcm_close(in->pcm);
7670 in->pcm = NULL;
7671 }
7672 }
7673 pthread_mutex_unlock(&adev->lock);
7674 return ret;
7675}
7676
7677static int in_get_mmap_position(const struct audio_stream_in *stream,
7678 struct audio_mmap_position *position)
7679{
7680 struct stream_in *in = (struct stream_in *)stream;
7681 ALOGVV("%s", __func__);
7682 if (position == NULL) {
7683 return -EINVAL;
7684 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307685 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007686 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307687 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007688 return -ENOSYS;
7689 }
7690 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307691 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007692 return -ENOSYS;
7693 }
7694 struct timespec ts = { 0, 0 };
7695 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7696 if (ret < 0) {
7697 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307698 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007699 return ret;
7700 }
Phil Burke0a86d12019-02-16 22:28:11 -08007701 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7702 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307703 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007704 return 0;
7705}
7706
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307707static int in_get_active_microphones(const struct audio_stream_in *stream,
7708 struct audio_microphone_characteristic_t *mic_array,
7709 size_t *mic_count) {
7710 struct stream_in *in = (struct stream_in *)stream;
7711 struct audio_device *adev = in->dev;
7712 ALOGVV("%s", __func__);
7713
7714 lock_input_stream(in);
7715 pthread_mutex_lock(&adev->lock);
7716 int ret = platform_get_active_microphones(adev->platform,
7717 audio_channel_count_from_in_mask(in->channel_mask),
7718 in->usecase, mic_array, mic_count);
7719 pthread_mutex_unlock(&adev->lock);
7720 pthread_mutex_unlock(&in->lock);
7721
7722 return ret;
7723}
7724
7725static int adev_get_microphones(const struct audio_hw_device *dev,
7726 struct audio_microphone_characteristic_t *mic_array,
7727 size_t *mic_count) {
7728 struct audio_device *adev = (struct audio_device *)dev;
7729 ALOGVV("%s", __func__);
7730
7731 pthread_mutex_lock(&adev->lock);
7732 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7733 pthread_mutex_unlock(&adev->lock);
7734
7735 return ret;
7736}
juyuchendb308c22019-01-21 11:57:17 -07007737
7738static void in_update_sink_metadata(struct audio_stream_in *stream,
7739 const struct sink_metadata *sink_metadata) {
7740
7741 if (stream == NULL
7742 || sink_metadata == NULL
7743 || sink_metadata->tracks == NULL) {
7744 return;
7745 }
7746
7747 int error = 0;
7748 struct stream_in *in = (struct stream_in *)stream;
7749 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007750 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007751 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007752
7753 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007754
7755 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007756 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007757
7758 lock_input_stream(in);
7759 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007760 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007761
Zhou Song62ea0282020-03-22 19:53:01 +08007762 is_ha_usecase = adev->ha_proxy_enable ?
7763 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7764 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7765 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007766 && adev->voice_tx_output != NULL) {
7767 /* Use the rx device from afe-proxy record to route voice call because
7768 there is no routing if tx device is on primary hal and rx device
7769 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007770 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007771
7772 if (!voice_is_call_state_active(adev)) {
7773 if (adev->mode == AUDIO_MODE_IN_CALL) {
7774 adev->current_call_output = adev->voice_tx_output;
7775 error = voice_start_call(adev);
7776 if (error != 0)
7777 ALOGE("%s: start voice call failed %d", __func__, error);
7778 }
7779 } else {
7780 adev->current_call_output = adev->voice_tx_output;
7781 voice_update_devices_for_all_voice_usecases(adev);
7782 }
7783 }
7784
7785 pthread_mutex_unlock(&adev->lock);
7786 pthread_mutex_unlock(&in->lock);
7787}
7788
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307789int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007790 audio_io_handle_t handle,
7791 audio_devices_t devices,
7792 audio_output_flags_t flags,
7793 struct audio_config *config,
7794 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007795 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796{
7797 struct audio_device *adev = (struct audio_device *)dev;
7798 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307799 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007800 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007801 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307802 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007803 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7804 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7805 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7806 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007807 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007808 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7809 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007810 bool force_haptic_path =
7811 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007812 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007813#ifdef AUDIO_GKI_ENABLED
7814 __s32 *generic_dec;
7815#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007816 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007817
kunleizdff872d2018-08-20 14:40:33 +08007818 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007819 is_usb_dev = false;
7820 devices = AUDIO_DEVICE_OUT_SPEAKER;
7821 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7822 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007823 if (config->format == AUDIO_FORMAT_DEFAULT)
7824 config->format = AUDIO_FORMAT_PCM_16_BIT;
7825 if (config->sample_rate == 0)
7826 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7827 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7828 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007829 }
7830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007831 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007833 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7834
Mingming Yin3a941d42016-02-17 18:08:05 -08007835 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007836 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7837 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307838
7839
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007840 if (!out) {
7841 return -ENOMEM;
7842 }
7843
Haynes Mathew George204045b2015-02-25 20:32:03 -08007844 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007845 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007846 pthread_mutexattr_init(&latch_attr);
7847 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
7848 pthread_mutex_init(&out->latch_lock, &latch_attr);
7849 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08007850 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007851 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007853 if (devices == AUDIO_DEVICE_NONE)
7854 devices = AUDIO_DEVICE_OUT_SPEAKER;
7855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007856 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007857 list_init(&out->device_list);
7858 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007859 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007860 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007861 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307862 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307863 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7864 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7865 else
7866 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007867 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007868 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007869 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307870 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307871 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007872 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007873 out->hal_output_suspend_supported = 0;
7874 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307875 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307876 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307877 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007878 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007879
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307880 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307881 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007882 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7883
Aalique Grahame22e49102018-12-18 14:23:57 -08007884 if (direct_dev &&
7885 (audio_is_linear_pcm(out->format) ||
7886 config->format == AUDIO_FORMAT_DEFAULT) &&
7887 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7888 audio_format_t req_format = config->format;
7889 audio_channel_mask_t req_channel_mask = config->channel_mask;
7890 uint32_t req_sample_rate = config->sample_rate;
7891
7892 pthread_mutex_lock(&adev->lock);
7893 if (is_hdmi) {
7894 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7895 ret = read_hdmi_sink_caps(out);
7896 if (config->sample_rate == 0)
7897 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7898 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7899 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7900 if (config->format == AUDIO_FORMAT_DEFAULT)
7901 config->format = AUDIO_FORMAT_PCM_16_BIT;
7902 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007903 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7904 &config->format,
7905 &out->supported_formats[0],
7906 MAX_SUPPORTED_FORMATS,
7907 &config->channel_mask,
7908 &out->supported_channel_masks[0],
7909 MAX_SUPPORTED_CHANNEL_MASKS,
7910 &config->sample_rate,
7911 &out->supported_sample_rates[0],
7912 MAX_SUPPORTED_SAMPLE_RATES);
7913 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007914 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007915
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007916 pthread_mutex_unlock(&adev->lock);
7917 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007918 if (ret == -ENOSYS) {
7919 /* ignore and go with default */
7920 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007921 }
7922 // For MMAP NO IRQ, allow conversions in ADSP
7923 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7924 goto error_open;
7925 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007926 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007927 goto error_open;
7928 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007929
7930 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7931 config->sample_rate = req_sample_rate;
7932 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7933 config->channel_mask = req_channel_mask;
7934 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7935 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007936 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007937
7938 out->sample_rate = config->sample_rate;
7939 out->channel_mask = config->channel_mask;
7940 out->format = config->format;
7941 if (is_hdmi) {
7942 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7943 out->config = pcm_config_hdmi_multi;
7944 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7945 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7946 out->config = pcm_config_mmap_playback;
7947 out->stream.start = out_start;
7948 out->stream.stop = out_stop;
7949 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7950 out->stream.get_mmap_position = out_get_mmap_position;
7951 } else {
7952 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7953 out->config = pcm_config_hifi;
7954 }
7955
7956 out->config.rate = out->sample_rate;
7957 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7958 if (is_hdmi) {
7959 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7960 audio_bytes_per_sample(out->format));
7961 }
7962 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007963 }
7964
Derek Chenf6318be2017-06-12 17:16:24 -04007965 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007966 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007967 /* extract car audio stream index */
7968 out->car_audio_stream =
7969 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7970 if (out->car_audio_stream < 0) {
7971 ALOGE("%s: invalid car audio stream %x",
7972 __func__, out->car_audio_stream);
7973 ret = -EINVAL;
7974 goto error_open;
7975 }
Derek Chen5f67a942020-02-24 23:08:13 -08007976 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007977 }
7978
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007979 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007980 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007981 if (!voice_extn_is_compress_voip_supported()) {
7982 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7983 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007984 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307985 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007986 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7987 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007988 out->volume_l = INVALID_OUT_VOLUME;
7989 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007990
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007991 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007992 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007993 uint32_t channel_count =
7994 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307995 out->config.channels = channel_count;
7996
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007997 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7998 out->sample_rate, out->format,
7999 channel_count, false);
8000 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
8001 if (frame_size != 0)
8002 out->config.period_size = buffer_size / frame_size;
8003 else
8004 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008005 }
8006 } else {
8007 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8008 voice_extn_compress_voip_is_active(out->dev)) &&
8009 (voice_extn_compress_voip_is_config_supported(config))) {
8010 ret = voice_extn_compress_voip_open_output_stream(out);
8011 if (ret != 0) {
8012 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8013 __func__, ret);
8014 goto error_open;
8015 }
Sujin Panicker19027262019-09-16 18:28:06 +05308016 } else {
8017 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8018 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008019 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008020 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008021 } else if (audio_is_linear_pcm(out->format) &&
8022 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8023 out->channel_mask = config->channel_mask;
8024 out->sample_rate = config->sample_rate;
8025 out->format = config->format;
8026 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8027 // does this change?
8028 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8029 out->config.rate = config->sample_rate;
8030 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8031 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8032 audio_bytes_per_sample(config->format));
8033 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008034 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308035 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308036 pthread_mutex_lock(&adev->lock);
8037 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8038 pthread_mutex_unlock(&adev->lock);
8039
8040 // reject offload during card offline to allow
8041 // fallback to s/w paths
8042 if (offline) {
8043 ret = -ENODEV;
8044 goto error_open;
8045 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008046
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008047 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8048 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8049 ALOGE("%s: Unsupported Offload information", __func__);
8050 ret = -EINVAL;
8051 goto error_open;
8052 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008053
Atul Khare3fa6e542017-08-09 00:56:17 +05308054 if (config->offload_info.format == 0)
8055 config->offload_info.format = config->format;
8056 if (config->offload_info.sample_rate == 0)
8057 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008058
Mingming Yin90310102013-11-13 16:57:00 -08008059 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308060 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008061 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008062 ret = -EINVAL;
8063 goto error_open;
8064 }
8065
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008066 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8067 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8068 (audio_extn_passthru_is_passthrough_stream(out)) &&
8069 !((config->sample_rate == 48000) ||
8070 (config->sample_rate == 96000) ||
8071 (config->sample_rate == 192000))) {
8072 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8073 __func__, config->sample_rate, config->offload_info.format);
8074 ret = -EINVAL;
8075 goto error_open;
8076 }
8077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008078 out->compr_config.codec = (struct snd_codec *)
8079 calloc(1, sizeof(struct snd_codec));
8080
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008081 if (!out->compr_config.codec) {
8082 ret = -ENOMEM;
8083 goto error_open;
8084 }
8085
Dhananjay Kumarac341582017-02-23 23:42:25 +05308086 out->stream.pause = out_pause;
8087 out->stream.resume = out_resume;
8088 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308089 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308090 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008091 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308092 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008093 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308094 } else {
8095 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8096 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008097 }
vivek mehta446c3962015-09-14 10:57:35 -07008098
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308099 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8100 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008101#ifdef AUDIO_GKI_ENABLED
8102 /* out->compr_config.codec->reserved[1] is for flags */
8103 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8104#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308105 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008106#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308107 }
8108
vivek mehta446c3962015-09-14 10:57:35 -07008109 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008110 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008111 config->format == 0 && config->sample_rate == 0 &&
8112 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008113 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008114 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8115 } else {
8116 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8117 ret = -EEXIST;
8118 goto error_open;
8119 }
vivek mehta446c3962015-09-14 10:57:35 -07008120 }
8121
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008122 if (config->offload_info.channel_mask)
8123 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008124 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008125 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008126 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008127 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308128 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008129 ret = -EINVAL;
8130 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008131 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008132
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008133 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008134 out->sample_rate = config->offload_info.sample_rate;
8135
Mingming Yin3ee55c62014-08-04 14:23:35 -07008136 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008137
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308138 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308139 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308140 audio_extn_dolby_send_ddp_endp_params(adev);
8141 audio_extn_dolby_set_dmid(adev);
8142 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008143
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008144 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008145 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008146 out->compr_config.codec->bit_rate =
8147 config->offload_info.bit_rate;
8148 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308149 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008150 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308151 /* Update bit width only for non passthrough usecases.
8152 * For passthrough usecases, the output will always be opened @16 bit
8153 */
8154 if (!audio_extn_passthru_is_passthrough_stream(out))
8155 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308156
8157 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008158#ifdef AUDIO_GKI_ENABLED
8159 /* out->compr_config.codec->reserved[1] is for flags */
8160 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8161 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8162#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308163 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8164 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008165#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308166
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008167 /*TODO: Do we need to change it for passthrough */
8168 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008169
Manish Dewangana6fc5442015-08-24 20:30:31 +05308170 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8171 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308172 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308173 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308174 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8175 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308176
8177 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8178 AUDIO_FORMAT_PCM) {
8179
8180 /*Based on platform support, configure appropriate alsa format for corresponding
8181 *hal input format.
8182 */
8183 out->compr_config.codec->format = hal_format_to_alsa(
8184 config->offload_info.format);
8185
Ashish Jain83a6cc22016-06-28 14:34:17 +05308186 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308187 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308188 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308189
Dhananjay Kumarac341582017-02-23 23:42:25 +05308190 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308191 *hal input format and alsa format might differ based on platform support.
8192 */
8193 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308194 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308195
8196 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8197
Deeraj Soman93155a62019-09-30 19:00:37 +05308198 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8199 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8200 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8201 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8202 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308203
Ashish Jainf1eaa582016-05-23 20:54:24 +05308204 /* Check if alsa session is configured with the same format as HAL input format,
8205 * if not then derive correct fragment size needed to accomodate the
8206 * conversion of HAL input format to alsa format.
8207 */
8208 audio_extn_utils_update_direct_pcm_fragment_size(out);
8209
8210 /*if hal input and output fragment size is different this indicates HAL input format is
8211 *not same as the alsa format
8212 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308213 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308214 /*Allocate a buffer to convert input data to the alsa configured format.
8215 *size of convert buffer is equal to the size required to hold one fragment size
8216 *worth of pcm data, this is because flinger does not write more than fragment_size
8217 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308218 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8219 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308220 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8221 ret = -ENOMEM;
8222 goto error_open;
8223 }
8224 }
8225 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8226 out->compr_config.fragment_size =
8227 audio_extn_passthru_get_buffer_size(&config->offload_info);
8228 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8229 } else {
8230 out->compr_config.fragment_size =
8231 platform_get_compress_offload_buffer_size(&config->offload_info);
8232 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8233 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008234
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308235 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8236 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8237 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008238 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8239#ifdef AUDIO_GKI_ENABLED
8240 generic_dec =
8241 &(out->compr_config.codec->options.generic.reserved[1]);
8242 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8243 AUDIO_OUTPUT_BIT_WIDTH;
8244#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308245 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008246#endif
8247 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008248
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308249 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8250 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8251 }
8252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008253 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8254 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008255
Manish Dewangan69426c82017-01-30 17:35:36 +05308256 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8257 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8258 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8259 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8260 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8261 } else {
8262 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8263 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008264
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308265 memset(&out->channel_map_param, 0,
8266 sizeof(struct audio_out_channel_map_param));
8267
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008268 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308269 out->send_next_track_params = false;
8270 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008271 out->offload_state = OFFLOAD_STATE_IDLE;
8272 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008273 out->writeAt.tv_sec = 0;
8274 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008275
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008276 audio_extn_dts_create_state_notifier_node(out->usecase);
8277
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008278 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8279 __func__, config->offload_info.version,
8280 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308281
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308282 /* Check if DSD audio format is supported in codec
8283 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308284 */
8285
8286 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308287 (!platform_check_codec_dsd_support(adev->platform) ||
8288 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308289 ret = -EINVAL;
8290 goto error_open;
8291 }
8292
Ashish Jain5106d362016-05-11 19:23:33 +05308293 /* Disable gapless if any of the following is true
8294 * passthrough playback
8295 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308296 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308297 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308298 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308299 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008300 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308301 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308302 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308303 check_and_set_gapless_mode(adev, false);
8304 } else
8305 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008306
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308307 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008308 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8309 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308310 if (config->format == AUDIO_FORMAT_DSD) {
8311 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008312#ifdef AUDIO_GKI_ENABLED
8313 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8314 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8315#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308316 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008317#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308318 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008319
8320 create_offload_callback_thread(out);
8321
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008322 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008323 switch (config->sample_rate) {
8324 case 0:
8325 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8326 break;
8327 case 8000:
8328 case 16000:
8329 case 48000:
8330 out->sample_rate = config->sample_rate;
8331 break;
8332 default:
8333 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8334 config->sample_rate);
8335 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8336 ret = -EINVAL;
8337 goto error_open;
8338 }
8339 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8340 switch (config->channel_mask) {
8341 case AUDIO_CHANNEL_NONE:
8342 case AUDIO_CHANNEL_OUT_STEREO:
8343 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8344 break;
8345 default:
8346 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8347 config->channel_mask);
8348 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8349 ret = -EINVAL;
8350 goto error_open;
8351 }
8352 switch (config->format) {
8353 case AUDIO_FORMAT_DEFAULT:
8354 case AUDIO_FORMAT_PCM_16_BIT:
8355 out->format = AUDIO_FORMAT_PCM_16_BIT;
8356 break;
8357 default:
8358 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8359 config->format);
8360 config->format = AUDIO_FORMAT_PCM_16_BIT;
8361 ret = -EINVAL;
8362 goto error_open;
8363 }
8364
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308365 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008366 if (ret != 0) {
8367 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008368 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008369 goto error_open;
8370 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008371 } else if (is_single_device_type_equal(&out->device_list,
8372 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008373 switch (config->sample_rate) {
8374 case 0:
8375 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8376 break;
8377 case 8000:
8378 case 16000:
8379 case 48000:
8380 out->sample_rate = config->sample_rate;
8381 break;
8382 default:
8383 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8384 config->sample_rate);
8385 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8386 ret = -EINVAL;
8387 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008388 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008389 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8390 switch (config->channel_mask) {
8391 case AUDIO_CHANNEL_NONE:
8392 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8393 break;
8394 case AUDIO_CHANNEL_OUT_STEREO:
8395 out->channel_mask = config->channel_mask;
8396 break;
8397 default:
8398 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8399 config->channel_mask);
8400 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8401 ret = -EINVAL;
8402 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008403 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008404 switch (config->format) {
8405 case AUDIO_FORMAT_DEFAULT:
8406 out->format = AUDIO_FORMAT_PCM_16_BIT;
8407 break;
8408 case AUDIO_FORMAT_PCM_16_BIT:
8409 out->format = config->format;
8410 break;
8411 default:
8412 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8413 config->format);
8414 config->format = AUDIO_FORMAT_PCM_16_BIT;
8415 ret = -EINVAL;
8416 break;
8417 }
8418 if (ret != 0)
8419 goto error_open;
8420
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008421 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8422 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008423 out->config.rate = out->sample_rate;
8424 out->config.channels =
8425 audio_channel_count_from_out_mask(out->channel_mask);
8426 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008427 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008428 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308429 unsigned int channels = 0;
8430 /*Update config params to default if not set by the caller*/
8431 if (config->sample_rate == 0)
8432 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8433 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8434 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8435 if (config->format == AUDIO_FORMAT_DEFAULT)
8436 config->format = AUDIO_FORMAT_PCM_16_BIT;
8437
8438 channels = audio_channel_count_from_out_mask(out->channel_mask);
8439
Varun Balaraje49253e2017-07-06 19:48:56 +05308440 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8441 out->usecase = get_interactive_usecase(adev);
8442 out->config = pcm_config_low_latency;
8443 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308444 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008445 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8446 out->flags);
8447 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008448 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8449 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8450 out->config = pcm_config_mmap_playback;
8451 out->stream.start = out_start;
8452 out->stream.stop = out_stop;
8453 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8454 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308455 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8456 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008457 out->hal_output_suspend_supported =
8458 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8459 out->dynamic_pm_qos_config_supported =
8460 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8461 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008462 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8463 } else {
8464 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8465 //the mixer path will be a string similar to "low-latency-playback resume"
8466 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8467 strlcat(out->pm_qos_mixer_path,
8468 " resume", MAX_MIXER_PATH_LEN);
8469 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8470 out->pm_qos_mixer_path);
8471 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308472 out->config = pcm_config_low_latency;
8473 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8474 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8475 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308476 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8477 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8478 if (out->config.period_size <= 0) {
8479 ALOGE("Invalid configuration period size is not valid");
8480 ret = -EINVAL;
8481 goto error_open;
8482 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008483 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8484 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8485 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008486 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8487 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8488 out->config = pcm_config_haptics_audio;
8489 if (force_haptic_path)
8490 adev->haptics_config = pcm_config_haptics_audio;
8491 else
8492 adev->haptics_config = pcm_config_haptics;
8493
Meng Wangd08ce322020-04-02 08:59:20 +08008494 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008495 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8496
8497 if (force_haptic_path) {
8498 out->config.channels = 1;
8499 adev->haptics_config.channels = 1;
8500 } else
8501 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 -08008502 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008503 ret = audio_extn_auto_hal_open_output_stream(out);
8504 if (ret) {
8505 ALOGE("%s: Failed to open output stream for bus device", __func__);
8506 ret = -EINVAL;
8507 goto error_open;
8508 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308509 } else {
8510 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008511 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8512 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308513 }
8514 out->hal_ip_format = format = out->format;
8515 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8516 out->hal_op_format = pcm_format_to_hal(out->config.format);
8517 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8518 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008519 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308520 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308521 if (out->hal_ip_format != out->hal_op_format) {
8522 uint32_t buffer_size = out->config.period_size *
8523 format_to_bitwidth_table[out->hal_op_format] *
8524 out->config.channels;
8525 out->convert_buffer = calloc(1, buffer_size);
8526 if (out->convert_buffer == NULL){
8527 ALOGE("Allocation failed for convert buffer for size %d",
8528 out->compr_config.fragment_size);
8529 ret = -ENOMEM;
8530 goto error_open;
8531 }
8532 ALOGD("Convert buffer allocated of size %d", buffer_size);
8533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534 }
8535
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008536 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8537 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308538
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008539 /* TODO remove this hardcoding and check why width is zero*/
8540 if (out->bit_width == 0)
8541 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308542 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008543 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008544 &out->device_list, out->flags,
8545 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308546 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308547 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008548 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008549 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8550 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008551 if(adev->primary_output == NULL)
8552 adev->primary_output = out;
8553 else {
8554 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008555 ret = -EEXIST;
8556 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008557 }
8558 }
8559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008560 /* Check if this usecase is already existing */
8561 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008562 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8563 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008564 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008565 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008566 ret = -EEXIST;
8567 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008568 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008570 pthread_mutex_unlock(&adev->lock);
8571
8572 out->stream.common.get_sample_rate = out_get_sample_rate;
8573 out->stream.common.set_sample_rate = out_set_sample_rate;
8574 out->stream.common.get_buffer_size = out_get_buffer_size;
8575 out->stream.common.get_channels = out_get_channels;
8576 out->stream.common.get_format = out_get_format;
8577 out->stream.common.set_format = out_set_format;
8578 out->stream.common.standby = out_standby;
8579 out->stream.common.dump = out_dump;
8580 out->stream.common.set_parameters = out_set_parameters;
8581 out->stream.common.get_parameters = out_get_parameters;
8582 out->stream.common.add_audio_effect = out_add_audio_effect;
8583 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8584 out->stream.get_latency = out_get_latency;
8585 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008586#ifdef NO_AUDIO_OUT
8587 out->stream.write = out_write_for_no_output;
8588#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008589 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008590#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008591 out->stream.get_render_position = out_get_render_position;
8592 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008593 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008594
Haynes Mathew George16081042017-05-31 17:16:49 -07008595 if (out->realtime)
8596 out->af_period_multiplier = af_period_multiplier;
8597 else
8598 out->af_period_multiplier = 1;
8599
Andy Hunga1f48fa2019-07-01 18:14:53 -07008600 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008602 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008603 out->volume_l = PLAYBACK_GAIN_MAX;
8604 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008605 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008606 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008607
8608 config->format = out->stream.common.get_format(&out->stream.common);
8609 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8610 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308611 register_format(out->format, out->supported_formats);
8612 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8613 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008614
Aalique Grahame22e49102018-12-18 14:23:57 -08008615 out->error_log = error_log_create(
8616 ERROR_LOG_ENTRIES,
8617 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8618
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308619 /*
8620 By locking output stream before registering, we allow the callback
8621 to update stream's state only after stream's initial state is set to
8622 adev state.
8623 */
8624 lock_output_stream(out);
8625 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8626 pthread_mutex_lock(&adev->lock);
8627 out->card_status = adev->card_status;
8628 pthread_mutex_unlock(&adev->lock);
8629 pthread_mutex_unlock(&out->lock);
8630
Aalique Grahame22e49102018-12-18 14:23:57 -08008631 stream_app_type_cfg_init(&out->app_type_cfg);
8632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008633 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308634 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008635 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008636
8637 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8638 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8639 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008640 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308641 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008642 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008643 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308644 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8645 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008646 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8647 out->usecase, PCM_PLAYBACK);
8648 hdlr_stream_cfg.flags = out->flags;
8649 hdlr_stream_cfg.type = PCM_PLAYBACK;
8650 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8651 &hdlr_stream_cfg);
8652 if (ret) {
8653 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8654 out->adsp_hdlr_stream_handle = NULL;
8655 }
8656 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308657 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8658 is_direct_passthough, false);
8659 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8660 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008661 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008662 if (ret < 0) {
8663 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8664 out->ip_hdlr_handle = NULL;
8665 }
8666 }
Derek Chenf939fb72018-11-13 13:34:41 -08008667
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008668 ret = io_streams_map_insert(adev, &out->stream.common,
8669 out->handle, AUDIO_PATCH_HANDLE_NONE);
8670 if (ret != 0)
8671 goto error_open;
8672
Susan Wang6dd13092021-01-25 10:27:11 -05008673 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008674
8675 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008676 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008677 pthread_mutex_unlock(&adev->lock);
8678
Eric Laurent994a6932013-07-17 11:51:42 -07008679 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008680 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008681
8682error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308683 if (out->convert_buffer)
8684 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008685 free(out);
8686 *stream_out = NULL;
8687 ALOGD("%s: exit: ret %d", __func__, ret);
8688 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008689}
8690
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308691void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008692 struct audio_stream_out *stream)
8693{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008694 struct stream_out *out = (struct stream_out *)stream;
8695 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008696 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008697
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008698 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308699
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008700 io_streams_map_remove(adev, out->handle);
8701
Susan Wang6dd13092021-01-25 10:27:11 -05008702 // remove out_ctxt early to prevent the stream
8703 // being opened in a race condition
8704 pthread_mutex_lock(&adev->lock);
8705 list_remove(&out->out_ctxt.list);
8706 pthread_mutex_unlock(&adev->lock);
8707
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308708 // must deregister from sndmonitor first to prevent races
8709 // between the callback and close_stream
8710 audio_extn_snd_mon_unregister_listener(out);
8711
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008712 /* close adsp hdrl session before standby */
8713 if (out->adsp_hdlr_stream_handle) {
8714 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8715 if (ret)
8716 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8717 out->adsp_hdlr_stream_handle = NULL;
8718 }
8719
Manish Dewangan21a850a2017-08-14 12:03:55 +05308720 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008721 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8722 out->ip_hdlr_handle = NULL;
8723 }
8724
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008725 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308726 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008727 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308728 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308729 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008730 if(ret != 0)
8731 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8732 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008733 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008734 out_standby(&stream->common);
8735
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008736 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008737 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008738 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008739 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008740 if (out->compr_config.codec != NULL)
8741 free(out->compr_config.codec);
8742 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008743
Zhou Songbaddf9f2020-11-20 13:57:39 +08008744 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308745
Varun Balaraje49253e2017-07-06 19:48:56 +05308746 if (is_interactive_usecase(out->usecase))
8747 free_interactive_usecase(adev, out->usecase);
8748
Ashish Jain83a6cc22016-06-28 14:34:17 +05308749 if (out->convert_buffer != NULL) {
8750 free(out->convert_buffer);
8751 out->convert_buffer = NULL;
8752 }
8753
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008754 if (adev->voice_tx_output == out)
8755 adev->voice_tx_output = NULL;
8756
Aalique Grahame22e49102018-12-18 14:23:57 -08008757 error_log_destroy(out->error_log);
8758 out->error_log = NULL;
8759
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308760 if (adev->primary_output == out)
8761 adev->primary_output = NULL;
8762
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008763 pthread_cond_destroy(&out->cond);
8764 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008765 pthread_mutex_destroy(&out->pre_lock);
8766 pthread_mutex_destroy(&out->latch_lock);
8767 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008768
8769 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008770 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008771 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008772 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008773}
8774
8775static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8776{
8777 struct audio_device *adev = (struct audio_device *)dev;
8778 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008780 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008781 int ret;
8782 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008783 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008784 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008785 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008786
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008787 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008788 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008789
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308790 if (!parms)
8791 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308792
Derek Chen6f293672019-04-01 01:40:24 -07008793 /* notify adev and input/output streams on the snd card status */
8794 adev_snd_mon_cb((void *)adev, parms);
8795
Weiyin Jiang24f55292020-12-22 14:35:46 +08008796 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8797 if (ret >= 0) {
8798 list_for_each(node, &adev->active_outputs_list) {
8799 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8800 streams_output_ctxt_t,
8801 list);
8802 out_snd_mon_cb((void *)out_ctxt->output, parms);
8803 }
Derek Chen6f293672019-04-01 01:40:24 -07008804
Weiyin Jiang24f55292020-12-22 14:35:46 +08008805 list_for_each(node, &adev->active_inputs_list) {
8806 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8807 streams_input_ctxt_t,
8808 list);
8809 in_snd_mon_cb((void *)in_ctxt->input, parms);
8810 }
Derek Chen6f293672019-04-01 01:40:24 -07008811 }
8812
Zhou Songd6d71752019-05-21 18:08:51 +08008813 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308814 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8815 if (ret >= 0) {
8816 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008817 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308818 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308819 /*
8820 * When ever BT_SCO=ON arrives, make sure to route
8821 * all use cases to SCO device, otherwise due to delay in
8822 * BT_SCO=ON and lack of synchronization with create audio patch
8823 * request for SCO device, some times use case not routed properly to
8824 * SCO device
8825 */
8826 struct audio_usecase *usecase;
8827 struct listnode *node;
8828 list_for_each(node, &adev->usecase_list) {
8829 usecase = node_to_item(node, struct audio_usecase, list);
Mingshu Pangef517202021-04-22 10:35:00 +08008830 if (usecase->stream.in && (usecase->type == PCM_CAPTURE ||
8831 usecase->type == VOICE_CALL) &&
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308832 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device))) {
8833 ALOGD("BT_SCO ON, switch all in use case to it");
8834 select_devices(adev, usecase->id);
8835 }
Mingshu Pangef517202021-04-22 10:35:00 +08008836 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
8837 usecase->type == VOICE_CALL) &&
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308838 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE))) {
8839 ALOGD("BT_SCO ON, switch all out use case to it");
8840 select_devices(adev, usecase->id);
8841 }
8842 }
8843 }
8844 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308845 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008846 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008847 }
8848 }
8849
8850 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008851 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008852 if (!strncmp(value, "false", 5) &&
8853 audio_extn_a2dp_source_is_suspended()) {
8854 struct audio_usecase *usecase;
8855 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008856 list_for_each(node, &adev->usecase_list) {
8857 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008858 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008859 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008860 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008861 reassign_device_list(&usecase->stream.in->device_list,
8862 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008863 select_devices(adev, usecase->id);
8864 }
Zhou Songd6d71752019-05-21 18:08:51 +08008865 }
8866 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308867 }
8868
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008869 status = voice_set_parameters(adev, parms);
8870 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008871 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008872
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008873 status = platform_set_parameters(adev->platform, parms);
8874 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008875 goto done;
8876
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008877 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8878 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008879 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8881 adev->bluetooth_nrec = true;
8882 else
8883 adev->bluetooth_nrec = false;
8884 }
8885
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008886 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8887 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008888 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8889 adev->screen_off = false;
8890 else
8891 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008892 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008893 }
8894
Eric Laurent4b084132018-10-19 17:33:43 -07008895 ret = str_parms_get_int(parms, "rotation", &val);
8896 if (ret >= 0) {
8897 bool reverse_speakers = false;
8898 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8899 switch (val) {
8900 // FIXME: note that the code below assumes that the speakers are in the correct placement
8901 // relative to the user when the device is rotated 90deg from its default rotation. This
8902 // assumption is device-specific, not platform-specific like this code.
8903 case 270:
8904 reverse_speakers = true;
8905 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8906 break;
8907 case 0:
8908 case 180:
8909 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8910 break;
8911 case 90:
8912 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8913 break;
8914 default:
8915 ALOGE("%s: unexpected rotation of %d", __func__, val);
8916 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008917 }
Eric Laurent4b084132018-10-19 17:33:43 -07008918 if (status == 0) {
8919 // check and set swap
8920 // - check if orientation changed and speaker active
8921 // - set rotation and cache the rotation value
8922 adev->camera_orientation =
8923 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8924 if (!audio_extn_is_maxx_audio_enabled())
8925 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8926 }
8927 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008928
Mingming Yin514a8bc2014-07-29 15:22:21 -07008929 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8930 if (ret >= 0) {
8931 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8932 adev->bt_wb_speech_enabled = true;
8933 else
8934 adev->bt_wb_speech_enabled = false;
8935 }
8936
Zhou Song12c29502019-03-16 10:37:18 +08008937 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8938 if (ret >= 0) {
8939 val = atoi(value);
8940 adev->swb_speech_mode = val;
8941 }
8942
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008943 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8944 if (ret >= 0) {
8945 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308946 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008947 if (audio_is_output_device(val) &&
8948 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008949 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008950 platform_get_controller_stream_from_params(parms, &controller, &stream);
8951 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8952 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008953 if (ret < 0) {
8954 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308955 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008956 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008957 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308958 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008959 /*
8960 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8961 * Per AudioPolicyManager, USB device is higher priority than WFD.
8962 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8963 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8964 * starting voice call on USB
8965 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008966 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308967 if (ret >= 0)
8968 audio_extn_usb_add_device(device, atoi(value));
8969
Zhou Song6f862822017-11-06 17:27:57 +08008970 if (!audio_extn_usb_is_tunnel_supported()) {
8971 ALOGV("detected USB connect .. disable proxy");
8972 adev->allow_afe_proxy_usage = false;
8973 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008974 }
8975 }
8976
8977 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8978 if (ret >= 0) {
8979 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308980 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008981 /*
8982 * The HDMI / Displayport disconnect handling has been moved to
8983 * audio extension to ensure that its parameters are not
8984 * invalidated prior to updating sysfs of the disconnect event
8985 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8986 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308987 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008988 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308989 if (ret >= 0)
8990 audio_extn_usb_remove_device(device, atoi(value));
8991
Zhou Song6f862822017-11-06 17:27:57 +08008992 if (!audio_extn_usb_is_tunnel_supported()) {
8993 ALOGV("detected USB disconnect .. enable proxy");
8994 adev->allow_afe_proxy_usage = true;
8995 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008996 }
8997 }
8998
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008999 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08009000
9001 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08009002 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309003 struct audio_usecase *usecase;
9004 struct listnode *node;
9005 list_for_each(node, &adev->usecase_list) {
9006 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009007 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9008 continue;
9009
9010 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309011 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309012 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309013 ALOGD("Switching to speaker and muting the stream before select_devices");
9014 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309015 //force device switch to re configure encoder
9016 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309017 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009018 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309019 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309020 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009021 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009022 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009023 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009024 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9025 reassign_device_list(&usecase->stream.out->device_list,
9026 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9027 check_a2dp_restore_l(adev, usecase->stream.out, true);
9028 break;
9029 }
9030 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309031 }
9032 }
9033 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009034
9035 //handle vr audio setparam
9036 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9037 value, sizeof(value));
9038 if (ret >= 0) {
9039 ALOGI("Setting vr mode to be %s", value);
9040 if (!strncmp(value, "true", 4)) {
9041 adev->vr_audio_mode_enabled = true;
9042 ALOGI("Setting vr mode to true");
9043 } else if (!strncmp(value, "false", 5)) {
9044 adev->vr_audio_mode_enabled = false;
9045 ALOGI("Setting vr mode to false");
9046 } else {
9047 ALOGI("wrong vr mode set");
9048 }
9049 }
9050
Eric Laurent4b084132018-10-19 17:33:43 -07009051 //FIXME: to be replaced by proper video capture properties API
9052 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9053 if (ret >= 0) {
9054 int camera_facing = CAMERA_FACING_BACK;
9055 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9056 camera_facing = CAMERA_FACING_FRONT;
9057 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9058 camera_facing = CAMERA_FACING_BACK;
9059 else {
9060 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9061 goto done;
9062 }
9063 adev->camera_orientation =
9064 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9065 struct audio_usecase *usecase;
9066 struct listnode *node;
9067 list_for_each(node, &adev->usecase_list) {
9068 usecase = node_to_item(node, struct audio_usecase, list);
9069 struct stream_in *in = usecase->stream.in;
9070 if (usecase->type == PCM_CAPTURE && in != NULL &&
9071 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9072 select_devices(adev, in->usecase);
9073 }
9074 }
9075 }
9076
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309077 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009078done:
9079 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009080 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309081error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009082 ALOGV("%s: exit with code(%d)", __func__, status);
9083 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009084}
9085
9086static char* adev_get_parameters(const struct audio_hw_device *dev,
9087 const char *keys)
9088{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309089 ALOGD("%s:%s", __func__, keys);
9090
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009091 struct audio_device *adev = (struct audio_device *)dev;
9092 struct str_parms *reply = str_parms_create();
9093 struct str_parms *query = str_parms_create_str(keys);
9094 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309095 char value[256] = {0};
9096 int ret = 0;
9097
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009098 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009099 if (reply) {
9100 str_parms_destroy(reply);
9101 }
9102 if (query) {
9103 str_parms_destroy(query);
9104 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009105 ALOGE("adev_get_parameters: failed to create query or reply");
9106 return NULL;
9107 }
9108
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009109 //handle vr audio getparam
9110
9111 ret = str_parms_get_str(query,
9112 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9113 value, sizeof(value));
9114
9115 if (ret >= 0) {
9116 bool vr_audio_enabled = false;
9117 pthread_mutex_lock(&adev->lock);
9118 vr_audio_enabled = adev->vr_audio_mode_enabled;
9119 pthread_mutex_unlock(&adev->lock);
9120
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009121 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009122
9123 if (vr_audio_enabled) {
9124 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9125 "true");
9126 goto exit;
9127 } else {
9128 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9129 "false");
9130 goto exit;
9131 }
9132 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009133
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009134 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009135 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009136 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009137 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009138 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009139 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309140 pthread_mutex_unlock(&adev->lock);
9141
Naresh Tannirud7205b62014-06-20 02:54:48 +05309142exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009143 str = str_parms_to_str(reply);
9144 str_parms_destroy(query);
9145 str_parms_destroy(reply);
9146
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009147 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009148 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149}
9150
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009151static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009152{
9153 return 0;
9154}
9155
9156static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9157{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009158 int ret;
9159 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009160
9161 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9162
Haynes Mathew George5191a852013-09-11 14:19:36 -07009163 pthread_mutex_lock(&adev->lock);
9164 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009165 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009166 pthread_mutex_unlock(&adev->lock);
9167 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009168}
9169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009170static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9171 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172{
9173 return -ENOSYS;
9174}
9175
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009176static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9177 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009178{
9179 return -ENOSYS;
9180}
9181
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009182static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9183 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009184{
9185 return -ENOSYS;
9186}
9187
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009188static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9189 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009190{
9191 return -ENOSYS;
9192}
9193
9194static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9195{
9196 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009197 struct listnode *node;
9198 struct audio_usecase *usecase = NULL;
9199 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009201 pthread_mutex_lock(&adev->lock);
9202 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309203 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9204 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009205 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009206 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309207 adev->current_call_output = adev->primary_output;
9208 voice_start_call(adev);
9209 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009210 (mode == AUDIO_MODE_NORMAL ||
9211 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009212 list_for_each(node, &adev->usecase_list) {
9213 usecase = node_to_item(node, struct audio_usecase, list);
9214 if (usecase->type == VOICE_CALL)
9215 break;
9216 }
9217 if (usecase &&
9218 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9219 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9220 true);
9221 if (ret != 0) {
9222 /* default service interval was successfully updated,
9223 reopen USB backend with new service interval */
9224 check_usecases_codec_backend(adev,
9225 usecase,
9226 usecase->out_snd_device);
9227 }
9228 }
9229
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009230 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009231 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009232 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009233 // restore device for other active usecases after stop call
9234 list_for_each(node, &adev->usecase_list) {
9235 usecase = node_to_item(node, struct audio_usecase, list);
9236 select_devices(adev, usecase->id);
9237 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009238 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009239 }
9240 pthread_mutex_unlock(&adev->lock);
9241 return 0;
9242}
9243
9244static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9245{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009246 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009247 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009248
9249 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009250 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009251 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009252
Derek Chend2530072014-11-24 12:39:14 -08009253 if (adev->ext_hw_plugin)
9254 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009255
9256 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009257 pthread_mutex_unlock(&adev->lock);
9258
9259 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009260}
9261
9262static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9263{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009264 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009265 return 0;
9266}
9267
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009268static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009269 const struct audio_config *config)
9270{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009271 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009272
Aalique Grahame22e49102018-12-18 14:23:57 -08009273 /* Don't know if USB HIFI in this context so use true to be conservative */
9274 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9275 true /*is_usb_hifi */) != 0)
9276 return 0;
9277
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009278 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9279 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009280}
9281
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009282static bool adev_input_allow_hifi_record(struct audio_device *adev,
9283 audio_devices_t devices,
9284 audio_input_flags_t flags,
9285 audio_source_t source) {
9286 const bool allowed = true;
9287
9288 if (!audio_is_usb_in_device(devices))
9289 return !allowed;
9290
9291 switch (flags) {
9292 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009293 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009294 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9295 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009296 default:
9297 return !allowed;
9298 }
9299
9300 switch (source) {
9301 case AUDIO_SOURCE_DEFAULT:
9302 case AUDIO_SOURCE_MIC:
9303 case AUDIO_SOURCE_UNPROCESSED:
9304 break;
9305 default:
9306 return !allowed;
9307 }
9308
9309 switch (adev->mode) {
9310 case 0:
9311 break;
9312 default:
9313 return !allowed;
9314 }
9315
9316 return allowed;
9317}
9318
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009319static int adev_update_voice_comm_input_stream(struct stream_in *in,
9320 struct audio_config *config)
9321{
9322 bool valid_rate = (config->sample_rate == 8000 ||
9323 config->sample_rate == 16000 ||
9324 config->sample_rate == 32000 ||
9325 config->sample_rate == 48000);
9326 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9327
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009328 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009329 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009330 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9331 in->config = default_pcm_config_voip_copp;
9332 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9333 DEFAULT_VOIP_BUF_DURATION_MS,
9334 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009335 } else {
9336 ALOGW("%s No valid input in voip, use defaults"
9337 "sample rate %u, channel mask 0x%X",
9338 __func__, config->sample_rate, in->channel_mask);
9339 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009340 in->config.rate = config->sample_rate;
9341 in->sample_rate = config->sample_rate;
9342 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009343 //XXX needed for voice_extn_compress_voip_open_input_stream
9344 in->config.rate = config->sample_rate;
9345 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309346 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009347 voice_extn_compress_voip_is_active(in->dev)) &&
9348 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9349 valid_rate && valid_ch) {
9350 voice_extn_compress_voip_open_input_stream(in);
9351 // update rate entries to match config from AF
9352 in->config.rate = config->sample_rate;
9353 in->sample_rate = config->sample_rate;
9354 } else {
9355 ALOGW("%s compress voip not active, use defaults", __func__);
9356 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009357 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009358 return 0;
9359}
9360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009361static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009362 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009363 audio_devices_t devices,
9364 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009365 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309366 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009367 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009368 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009369{
9370 struct audio_device *adev = (struct audio_device *)dev;
9371 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009372 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009373 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009374 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309375 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009376 bool is_usb_dev = audio_is_usb_in_device(devices);
9377 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9378 devices,
9379 flags,
9380 source);
Andy Hung94320602018-10-29 18:31:12 -07009381 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9382 " sample_rate %u, channel_mask %#x, format %#x",
9383 __func__, flags, is_usb_dev, may_use_hifi_record,
9384 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309385
kunleizdff872d2018-08-20 14:40:33 +08009386 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009387 is_usb_dev = false;
9388 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9389 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9390 __func__, devices);
9391 }
9392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009393 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009394
9395 if (!(is_usb_dev && may_use_hifi_record)) {
9396 if (config->sample_rate == 0)
9397 config->sample_rate = 48000;
9398 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9399 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9400 if (config->format == AUDIO_FORMAT_DEFAULT)
9401 config->format = AUDIO_FORMAT_PCM_16_BIT;
9402
9403 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9404
Aalique Grahame22e49102018-12-18 14:23:57 -08009405 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9406 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009407 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309408 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009409
9410 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009411
9412 if (!in) {
9413 ALOGE("failed to allocate input stream");
9414 return -ENOMEM;
9415 }
9416
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309417 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309418 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9419 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009420 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009421 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009423 in->stream.common.get_sample_rate = in_get_sample_rate;
9424 in->stream.common.set_sample_rate = in_set_sample_rate;
9425 in->stream.common.get_buffer_size = in_get_buffer_size;
9426 in->stream.common.get_channels = in_get_channels;
9427 in->stream.common.get_format = in_get_format;
9428 in->stream.common.set_format = in_set_format;
9429 in->stream.common.standby = in_standby;
9430 in->stream.common.dump = in_dump;
9431 in->stream.common.set_parameters = in_set_parameters;
9432 in->stream.common.get_parameters = in_get_parameters;
9433 in->stream.common.add_audio_effect = in_add_audio_effect;
9434 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9435 in->stream.set_gain = in_set_gain;
9436 in->stream.read = in_read;
9437 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009438 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309439 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009440 in->stream.set_microphone_direction = in_set_microphone_direction;
9441 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009442 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009443
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009444 list_init(&in->device_list);
9445 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009446 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009447 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009448 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009449 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009450 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009451 in->bit_width = 16;
9452 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009453 in->direction = MIC_DIRECTION_UNSPECIFIED;
9454 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009455 list_init(&in->aec_list);
9456 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009457 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009458
Andy Hung94320602018-10-29 18:31:12 -07009459 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009460 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9461 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9462 /* Force channel config requested to mono if incall
9463 record is being requested for only uplink/downlink */
9464 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9465 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9466 ret = -EINVAL;
9467 goto err_open;
9468 }
9469 }
9470
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009471 if (is_usb_dev && may_use_hifi_record) {
9472 /* HiFi record selects an appropriate format, channel, rate combo
9473 depending on sink capabilities*/
9474 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9475 &config->format,
9476 &in->supported_formats[0],
9477 MAX_SUPPORTED_FORMATS,
9478 &config->channel_mask,
9479 &in->supported_channel_masks[0],
9480 MAX_SUPPORTED_CHANNEL_MASKS,
9481 &config->sample_rate,
9482 &in->supported_sample_rates[0],
9483 MAX_SUPPORTED_SAMPLE_RATES);
9484 if (ret != 0) {
9485 ret = -EINVAL;
9486 goto err_open;
9487 }
9488 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009489 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309490 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309491 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9492 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9493 in->config.format = PCM_FORMAT_S32_LE;
9494 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309495 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9496 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9497 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9498 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9499 bool ret_error = false;
9500 in->bit_width = 24;
9501 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9502 from HAL is 24_packed and 8_24
9503 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9504 24_packed return error indicating supported format is 24_packed
9505 *> In case of any other source requesting 24 bit or float return error
9506 indicating format supported is 16 bit only.
9507
9508 on error flinger will retry with supported format passed
9509 */
9510 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9511 (source != AUDIO_SOURCE_CAMCORDER)) {
9512 config->format = AUDIO_FORMAT_PCM_16_BIT;
9513 if (config->sample_rate > 48000)
9514 config->sample_rate = 48000;
9515 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009516 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9517 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309518 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9519 ret_error = true;
9520 }
9521
9522 if (ret_error) {
9523 ret = -EINVAL;
9524 goto err_open;
9525 }
9526 }
9527
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009528 in->channel_mask = config->channel_mask;
9529 in->format = config->format;
9530
9531 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309532
Huicheng Liu1404ba12020-09-11 01:03:25 -04009533 /* validate bus device address */
9534 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9535 /* extract car audio stream index */
9536 in->car_audio_stream =
9537 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9538 if (in->car_audio_stream < 0) {
9539 ALOGE("%s: invalid car audio stream %x",
9540 __func__, in->car_audio_stream);
9541 ret = -EINVAL;
9542 goto err_open;
9543 }
9544 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009545 ret = audio_extn_auto_hal_open_input_stream(in);
9546 if (ret) {
9547 ALOGE("%s: Failed to open input stream for bus device", __func__);
9548 ret = -EINVAL;
9549 goto err_open;
9550 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009551 }
9552
Susan Wange3959562021-03-11 11:50:26 -05009553 /* reassign use case for echo reference stream on automotive platforms */
9554 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9555 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9556 }
9557
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309558 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9559 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9560 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9561 else {
9562 ret = -EINVAL;
9563 goto err_open;
9564 }
9565 }
9566
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009567 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309568 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9569 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009570 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9571 is_low_latency = true;
9572#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309573 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9574 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9575 else
9576 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009577#endif
9578 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009579 if (!in->realtime) {
9580 in->config = pcm_config_audio_capture;
9581 frame_size = audio_stream_in_frame_size(&in->stream);
9582 buffer_size = get_input_buffer_size(config->sample_rate,
9583 config->format,
9584 channel_count,
9585 is_low_latency);
9586 in->config.period_size = buffer_size / frame_size;
9587 in->config.rate = config->sample_rate;
9588 in->af_period_multiplier = 1;
9589 } else {
9590 // period size is left untouched for rt mode playback
9591 in->config = pcm_config_audio_capture_rt;
9592 in->af_period_multiplier = af_period_multiplier;
9593 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009594 }
9595
9596 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9597 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9598 in->realtime = 0;
9599 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9600 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009601 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009602 in->stream.start = in_start;
9603 in->stream.stop = in_stop;
9604 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9605 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009606 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009607 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009608 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9609 in->config = pcm_config_audio_capture;
9610 frame_size = audio_stream_in_frame_size(&in->stream);
9611 buffer_size = get_input_buffer_size(config->sample_rate,
9612 config->format,
9613 channel_count,
9614 false /*is_low_latency*/);
9615 in->config.period_size = buffer_size / frame_size;
9616 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009617 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009618 switch (config->format) {
9619 case AUDIO_FORMAT_PCM_32_BIT:
9620 in->bit_width = 32;
9621 break;
9622 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9623 case AUDIO_FORMAT_PCM_8_24_BIT:
9624 in->bit_width = 24;
9625 break;
9626 default:
9627 in->bit_width = 16;
9628 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009629 } else if (is_single_device_type_equal(&in->device_list,
9630 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9631 is_single_device_type_equal(&in->device_list,
9632 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009633 if (config->sample_rate == 0)
9634 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9635 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9636 config->sample_rate != 8000) {
9637 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9638 ret = -EINVAL;
9639 goto err_open;
9640 }
9641 if (config->format == AUDIO_FORMAT_DEFAULT)
9642 config->format = AUDIO_FORMAT_PCM_16_BIT;
9643 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9644 config->format = AUDIO_FORMAT_PCM_16_BIT;
9645 ret = -EINVAL;
9646 goto err_open;
9647 }
9648
9649 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009650 if (adev->ha_proxy_enable &&
9651 is_single_device_type_equal(&in->device_list,
9652 AUDIO_DEVICE_IN_TELEPHONY_RX))
9653 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009654 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009655 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009656 in->af_period_multiplier = 1;
9657 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309658 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009659 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9660 (config->sample_rate == 8000 ||
9661 config->sample_rate == 16000 ||
9662 config->sample_rate == 32000 ||
9663 config->sample_rate == 48000) &&
9664 channel_count == 1) {
9665 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9666 in->config = pcm_config_audio_capture;
9667 frame_size = audio_stream_in_frame_size(&in->stream);
9668 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9669 config->sample_rate,
9670 config->format,
9671 channel_count, false /*is_low_latency*/);
9672 in->config.period_size = buffer_size / frame_size;
9673 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9674 in->config.rate = config->sample_rate;
9675 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009676 } else if (in->realtime) {
9677 in->config = pcm_config_audio_capture_rt;
9678 in->config.format = pcm_format_from_audio_format(config->format);
9679 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009680 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309681 int ret_val;
9682 pthread_mutex_lock(&adev->lock);
9683 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9684 in, config, &channel_mask_updated);
9685 pthread_mutex_unlock(&adev->lock);
9686
9687 if (!ret_val) {
9688 if (channel_mask_updated == true) {
9689 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9690 __func__, config->channel_mask);
9691 ret = -EINVAL;
9692 goto err_open;
9693 }
9694 ALOGD("%s: created multi-channel session succesfully",__func__);
9695 } else if (audio_extn_compr_cap_enabled() &&
9696 audio_extn_compr_cap_format_supported(config->format) &&
9697 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9698 audio_extn_compr_cap_init(in);
9699 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309700 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309701 if (ret)
9702 goto err_open;
9703 } else {
9704 in->config = pcm_config_audio_capture;
9705 in->config.rate = config->sample_rate;
9706 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309707 in->format = config->format;
9708 frame_size = audio_stream_in_frame_size(&in->stream);
9709 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009710 config->format,
9711 channel_count,
9712 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009713 /* prevent division-by-zero */
9714 if (frame_size == 0) {
9715 ALOGE("%s: Error frame_size==0", __func__);
9716 ret = -EINVAL;
9717 goto err_open;
9718 }
9719
Revathi Uddarajud2634032017-12-07 14:42:34 +05309720 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009721 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009722
Revathi Uddarajud2634032017-12-07 14:42:34 +05309723 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9724 /* optionally use VOIP usecase depending on config(s) */
9725 ret = adev_update_voice_comm_input_stream(in, config);
9726 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009727
Revathi Uddarajud2634032017-12-07 14:42:34 +05309728 if (ret) {
9729 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9730 goto err_open;
9731 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009732 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309733
9734 /* assign concurrent capture usecase if record has to caried out from
9735 * actual hardware input source */
9736 if (audio_extn_is_concurrent_capture_enabled() &&
9737 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309738 /* Acquire lock to avoid two concurrent use cases initialized to
9739 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009740
Samyak Jainc37062f2019-04-25 18:41:06 +05309741 if (in->usecase == USECASE_AUDIO_RECORD) {
9742 pthread_mutex_lock(&adev->lock);
9743 if (!(adev->pcm_record_uc_state)) {
9744 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9745 adev->pcm_record_uc_state = 1;
9746 pthread_mutex_unlock(&adev->lock);
9747 } else {
9748 pthread_mutex_unlock(&adev->lock);
9749 /* Assign compress record use case for second record */
9750 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9751 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9752 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9753 if (audio_extn_cin_applicable_stream(in)) {
9754 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309755 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309756 if (ret)
9757 goto err_open;
9758 }
9759 }
9760 }
kunleiz28c73e72019-03-27 17:24:04 +08009761 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009762 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309763 if (audio_extn_ssr_get_stream() != in)
9764 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009765
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009766 in->sample_rate = in->config.rate;
9767
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309768 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9769 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009770 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009771 in->sample_rate, in->bit_width,
9772 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309773 register_format(in->format, in->supported_formats);
9774 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9775 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309776
Aalique Grahame22e49102018-12-18 14:23:57 -08009777 in->error_log = error_log_create(
9778 ERROR_LOG_ENTRIES,
9779 1000000000 /* aggregate consecutive identical errors within one second */);
9780
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009781 /* This stream could be for sound trigger lab,
9782 get sound trigger pcm if present */
9783 audio_extn_sound_trigger_check_and_get_session(in);
9784
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309785 lock_input_stream(in);
9786 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9787 pthread_mutex_lock(&adev->lock);
9788 in->card_status = adev->card_status;
9789 pthread_mutex_unlock(&adev->lock);
9790 pthread_mutex_unlock(&in->lock);
9791
Aalique Grahame22e49102018-12-18 14:23:57 -08009792 stream_app_type_cfg_init(&in->app_type_cfg);
9793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009794 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009795
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009796 ret = io_streams_map_insert(adev, &in->stream.common,
9797 handle, AUDIO_PATCH_HANDLE_NONE);
9798 if (ret != 0)
9799 goto err_open;
9800
Susan Wang6dd13092021-01-25 10:27:11 -05009801 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009802
9803 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009804 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009805 pthread_mutex_unlock(&adev->lock);
9806
Eric Laurent994a6932013-07-17 11:51:42 -07009807 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009808 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009809
9810err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309811 if (in->usecase == USECASE_AUDIO_RECORD) {
9812 pthread_mutex_lock(&adev->lock);
9813 adev->pcm_record_uc_state = 0;
9814 pthread_mutex_unlock(&adev->lock);
9815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009816 free(in);
9817 *stream_in = NULL;
9818 return ret;
9819}
9820
9821static void adev_close_input_stream(struct audio_hw_device *dev,
9822 struct audio_stream_in *stream)
9823{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009824 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009825 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009826 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309827
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309828 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009829
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009830 if (in == NULL) {
9831 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9832 return;
9833 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009834 io_streams_map_remove(adev, in->capture_handle);
9835
Susan Wang6dd13092021-01-25 10:27:11 -05009836 // remove out_ctxt early to prevent the stream
9837 // being opened in a race condition
9838 pthread_mutex_lock(&adev->lock);
9839 list_remove(&in->in_ctxt.list);
9840 pthread_mutex_unlock(&adev->lock);
9841
kunleiz70e57612018-12-28 17:50:23 +08009842 /* must deregister from sndmonitor first to prevent races
9843 * between the callback and close_stream
9844 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309845 audio_extn_snd_mon_unregister_listener(stream);
9846
kunleiz70e57612018-12-28 17:50:23 +08009847 /* Disable echo reference if there are no active input, hfp call
9848 * and sound trigger while closing input stream
9849 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009850 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009851 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009852 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9853 struct listnode out_devices;
9854 list_init(&out_devices);
9855 platform_set_echo_reference(adev, false, &out_devices);
9856 } else
kunleiz70e57612018-12-28 17:50:23 +08009857 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309858
Weiyin Jiang2995f662019-04-17 14:25:12 +08009859 error_log_destroy(in->error_log);
9860 in->error_log = NULL;
9861
Pallavid7c7a272018-01-16 11:22:55 +05309862
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009863 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309864 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009865 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309866 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009867 if (ret != 0)
9868 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9869 __func__, ret);
9870 } else
9871 in_standby(&stream->common);
9872
Weiyin Jiang280ea742020-09-08 20:28:22 +08009873 pthread_mutex_destroy(&in->lock);
9874 pthread_mutex_destroy(&in->pre_lock);
9875
Revathi Uddarajud2634032017-12-07 14:42:34 +05309876 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309877 if (in->usecase == USECASE_AUDIO_RECORD) {
9878 adev->pcm_record_uc_state = 0;
9879 }
9880
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009881 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9882 adev->enable_voicerx = false;
9883 }
9884
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009885 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009886 audio_extn_ssr_deinit();
9887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009888
Garmond Leunge2433c32017-09-28 21:51:22 -07009889 if (audio_extn_ffv_get_stream() == in) {
9890 audio_extn_ffv_stream_deinit();
9891 }
9892
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309893 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009894 audio_extn_compr_cap_format_supported(in->config.format))
9895 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309896
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309897 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309898 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009899
Mingming Yinfd7607b2016-01-22 12:48:44 -08009900 if (in->is_st_session) {
9901 ALOGV("%s: sound trigger pcm stop lab", __func__);
9902 audio_extn_sound_trigger_stop_lab(in);
9903 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009904 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309905 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009906 return;
9907}
9908
Aalique Grahame22e49102018-12-18 14:23:57 -08009909/* verifies input and output devices and their capabilities.
9910 *
9911 * This verification is required when enabling extended bit-depth or
9912 * sampling rates, as not all qcom products support it.
9913 *
9914 * Suitable for calling only on initialization such as adev_open().
9915 * It fills the audio_device use_case_table[] array.
9916 *
9917 * Has a side-effect that it needs to configure audio routing / devices
9918 * in order to power up the devices and read the device parameters.
9919 * It does not acquire any hw device lock. Should restore the devices
9920 * back to "normal state" upon completion.
9921 */
9922static int adev_verify_devices(struct audio_device *adev)
9923{
9924 /* enumeration is a bit difficult because one really wants to pull
9925 * the use_case, device id, etc from the hidden pcm_device_table[].
9926 * In this case there are the following use cases and device ids.
9927 *
9928 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9929 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9930 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9931 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9932 * [USECASE_AUDIO_RECORD] = {0, 0},
9933 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9934 * [USECASE_VOICE_CALL] = {2, 2},
9935 *
9936 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9937 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9938 */
9939
9940 /* should be the usecases enabled in adev_open_input_stream() */
9941 static const int test_in_usecases[] = {
9942 USECASE_AUDIO_RECORD,
9943 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9944 };
9945 /* should be the usecases enabled in adev_open_output_stream()*/
9946 static const int test_out_usecases[] = {
9947 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9948 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9949 };
9950 static const usecase_type_t usecase_type_by_dir[] = {
9951 PCM_PLAYBACK,
9952 PCM_CAPTURE,
9953 };
9954 static const unsigned flags_by_dir[] = {
9955 PCM_OUT,
9956 PCM_IN,
9957 };
9958
9959 size_t i;
9960 unsigned dir;
9961 const unsigned card_id = adev->snd_card;
9962
9963 for (dir = 0; dir < 2; ++dir) {
9964 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9965 const unsigned flags_dir = flags_by_dir[dir];
9966 const size_t testsize =
9967 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9968 const int *testcases =
9969 dir ? test_in_usecases : test_out_usecases;
9970 const audio_devices_t audio_device =
9971 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9972
9973 for (i = 0; i < testsize; ++i) {
9974 const audio_usecase_t audio_usecase = testcases[i];
9975 int device_id;
9976 struct pcm_params **pparams;
9977 struct stream_out out;
9978 struct stream_in in;
9979 struct audio_usecase uc_info;
9980 int retval;
9981
9982 pparams = &adev->use_case_table[audio_usecase];
9983 pcm_params_free(*pparams); /* can accept null input */
9984 *pparams = NULL;
9985
9986 /* find the device ID for the use case (signed, for error) */
9987 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9988 if (device_id < 0)
9989 continue;
9990
9991 /* prepare structures for device probing */
9992 memset(&uc_info, 0, sizeof(uc_info));
9993 uc_info.id = audio_usecase;
9994 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009995 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009996 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009997 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009998 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009999 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010000 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
10001 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -080010002 }
10003 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010004 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010005 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010006 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010007 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010008 uc_info.in_snd_device = SND_DEVICE_NONE;
10009 uc_info.out_snd_device = SND_DEVICE_NONE;
10010 list_add_tail(&adev->usecase_list, &uc_info.list);
10011
10012 /* select device - similar to start_(in/out)put_stream() */
10013 retval = select_devices(adev, audio_usecase);
10014 if (retval >= 0) {
10015 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10016#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010017 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010018 if (*pparams) {
10019 ALOGV("%s: (%s) card %d device %d", __func__,
10020 dir ? "input" : "output", card_id, device_id);
10021 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10022 } else {
10023 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10024 }
10025#endif
10026 }
10027
10028 /* deselect device - similar to stop_(in/out)put_stream() */
10029 /* 1. Get and set stream specific mixer controls */
10030 retval = disable_audio_route(adev, &uc_info);
10031 /* 2. Disable the rx device */
10032 retval = disable_snd_device(adev,
10033 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10034 list_remove(&uc_info.list);
10035 }
10036 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010037 return 0;
10038}
10039
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010040int update_patch(unsigned int num_sources,
10041 const struct audio_port_config *sources,
10042 unsigned int num_sinks,
10043 const struct audio_port_config *sinks,
10044 audio_patch_handle_t handle,
10045 struct audio_patch_info *p_info,
10046 patch_type_t patch_type, bool new_patch)
10047{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010048 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049
10050 if (p_info == NULL) {
10051 ALOGE("%s: Invalid patch pointer", __func__);
10052 return -EINVAL;
10053 }
10054
10055 if (new_patch) {
10056 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10057 if (p_info->patch == NULL) {
10058 ALOGE("%s: Could not allocate patch", __func__);
10059 return -ENOMEM;
10060 }
10061 }
10062
10063 p_info->patch->id = handle;
10064 p_info->patch->num_sources = num_sources;
10065 p_info->patch->num_sinks = num_sinks;
10066
10067 for (int i = 0; i < num_sources; i++)
10068 p_info->patch->sources[i] = sources[i];
10069 for (int i = 0; i < num_sinks; i++)
10070 p_info->patch->sinks[i] = sinks[i];
10071
10072 p_info->patch_type = patch_type;
10073 return 0;
10074}
10075
10076audio_patch_handle_t generate_patch_handle()
10077{
10078 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10079 if (++patch_handle < 0)
10080 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10081 return patch_handle;
10082}
10083
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010084int adev_create_audio_patch(struct audio_hw_device *dev,
10085 unsigned int num_sources,
10086 const struct audio_port_config *sources,
10087 unsigned int num_sinks,
10088 const struct audio_port_config *sinks,
10089 audio_patch_handle_t *handle)
10090{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010091 int ret = 0;
10092 struct audio_device *adev = (struct audio_device *)dev;
10093 struct audio_patch_info *p_info = NULL;
10094 patch_type_t patch_type = PATCH_NONE;
10095 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10096 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10097 struct audio_stream_info *s_info = NULL;
10098 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010099 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10101 bool new_patch = false;
10102 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010103
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10105 num_sources, num_sinks, *handle);
10106
10107 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10108 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10109 ALOGE("%s: Invalid patch arguments", __func__);
10110 ret = -EINVAL;
10111 goto done;
10112 }
10113
10114 if (num_sources > 1) {
10115 ALOGE("%s: Multiple sources are not supported", __func__);
10116 ret = -EINVAL;
10117 goto done;
10118 }
10119
10120 if (sources == NULL || sinks == NULL) {
10121 ALOGE("%s: Invalid sources or sinks port config", __func__);
10122 ret = -EINVAL;
10123 goto done;
10124 }
10125
10126 ALOGV("%s: source role %d, source type %d", __func__,
10127 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010128 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129
10130 // Populate source/sink information and fetch stream info
10131 switch (sources[0].type) {
10132 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10133 device_type = sources[0].ext.device.type;
10134 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010135 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010136 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10137 patch_type = PATCH_CAPTURE;
10138 io_handle = sinks[0].ext.mix.handle;
10139 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010140 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010141 __func__, device_type, io_handle);
10142 } else {
10143 // Device to device patch is not implemented.
10144 // This space will need changes if audio HAL
10145 // handles device to device patches in the future.
10146 patch_type = PATCH_DEVICE_LOOPBACK;
10147 }
10148 break;
10149 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10150 io_handle = sources[0].ext.mix.handle;
10151 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010152 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010154 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010155 }
10156 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010157 ALOGD("%s: Playback patch from mix handle %d to device %x",
10158 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010159 break;
10160 case AUDIO_PORT_TYPE_SESSION:
10161 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010162 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10163 ret = -EINVAL;
10164 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165 }
10166
10167 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010168
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 // Generate patch info and update patch
10170 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010171 *handle = generate_patch_handle();
10172 p_info = (struct audio_patch_info *)
10173 calloc(1, sizeof(struct audio_patch_info));
10174 if (p_info == NULL) {
10175 ALOGE("%s: Failed to allocate memory", __func__);
10176 pthread_mutex_unlock(&adev->lock);
10177 ret = -ENOMEM;
10178 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010179 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010180 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010181 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010182 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010183 if (p_info == NULL) {
10184 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10185 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010186 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 ret = -EINVAL;
10188 goto done;
10189 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010190 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010191 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010192 *handle, p_info, patch_type, new_patch);
10193
10194 // Fetch stream info of associated mix for playback or capture patches
10195 if (p_info->patch_type == PATCH_PLAYBACK ||
10196 p_info->patch_type == PATCH_CAPTURE) {
10197 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10198 if (s_info == NULL) {
10199 ALOGE("%s: Failed to obtain stream info", __func__);
10200 if (new_patch)
10201 free(p_info);
10202 pthread_mutex_unlock(&adev->lock);
10203 ret = -EINVAL;
10204 goto done;
10205 }
10206 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10207 s_info->patch_handle = *handle;
10208 stream = s_info->stream;
10209 }
10210 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211
10212 // Update routing for stream
10213 if (stream != NULL) {
10214 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010215 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010216 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010217 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010218 if (ret < 0) {
10219 pthread_mutex_lock(&adev->lock);
10220 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10221 if (new_patch)
10222 free(p_info);
10223 pthread_mutex_unlock(&adev->lock);
10224 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10225 goto done;
10226 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010227 }
10228
10229 // Add new patch to patch map
10230 if (!ret && new_patch) {
10231 pthread_mutex_lock(&adev->lock);
10232 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010233 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010234 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010235 }
10236
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010237done:
10238 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010239 num_sources,
10240 sources,
10241 num_sinks,
10242 sinks,
10243 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010244 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010245 num_sources,
10246 sources,
10247 num_sinks,
10248 sinks,
10249 handle);
10250 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010251}
10252
10253int adev_release_audio_patch(struct audio_hw_device *dev,
10254 audio_patch_handle_t handle)
10255{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010256 struct audio_device *adev = (struct audio_device *) dev;
10257 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010258 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010259 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010260
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010261 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10262 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10263 ret = -EINVAL;
10264 goto done;
10265 }
10266
10267 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010268 pthread_mutex_lock(&adev->lock);
10269 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010270 if (p_info == NULL) {
10271 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010272 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010273 ret = -EINVAL;
10274 goto done;
10275 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010276 struct audio_patch *patch = p_info->patch;
10277 if (patch == NULL) {
10278 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010279 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010280 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010281 goto done;
10282 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010283 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10284 switch (patch->sources[0].type) {
10285 case AUDIO_PORT_TYPE_MIX:
10286 io_handle = patch->sources[0].ext.mix.handle;
10287 break;
10288 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010289 if (p_info->patch_type == PATCH_CAPTURE)
10290 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010291 break;
10292 case AUDIO_PORT_TYPE_SESSION:
10293 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010294 pthread_mutex_unlock(&adev->lock);
10295 ret = -EINVAL;
10296 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010297 }
10298
10299 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010300 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010301 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010302 if (patch_type == PATCH_PLAYBACK ||
10303 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010304 struct audio_stream_info *s_info =
10305 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10306 if (s_info == NULL) {
10307 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10308 pthread_mutex_unlock(&adev->lock);
10309 goto done;
10310 }
10311 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10312 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010313 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010314 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010315
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010316 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010317 struct listnode devices;
10318 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010319 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010320 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010321 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010322 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010323 }
10324
10325 if (ret < 0)
10326 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10327
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010328done:
10329 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10330 audio_extn_auto_hal_release_audio_patch(dev, handle);
10331
10332 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010333 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010334}
10335
10336int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10337{
Derek Chenf13dd492018-11-13 14:53:51 -080010338 int ret = 0;
10339
10340 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10341 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10342 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010343}
10344
10345int adev_set_audio_port_config(struct audio_hw_device *dev,
10346 const struct audio_port_config *config)
10347{
Derek Chenf13dd492018-11-13 14:53:51 -080010348 int ret = 0;
10349
10350 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10351 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10352 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010353}
10354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010355static int adev_dump(const audio_hw_device_t *device __unused,
10356 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010357{
10358 return 0;
10359}
10360
10361static int adev_close(hw_device_t *device)
10362{
Aalique Grahame22e49102018-12-18 14:23:57 -080010363 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010364 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010365
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010366 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010367 return 0;
10368
10369 pthread_mutex_lock(&adev_init_lock);
10370
10371 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010372 if (audio_extn_spkr_prot_is_enabled())
10373 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010374 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010375 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010376 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010377 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010378 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010379 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010380 audio_extn_utils_release_streams_cfg_lists(
10381 &adev->streams_output_cfg_list,
10382 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010383 if (audio_extn_qap_is_enabled())
10384 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010385 if (audio_extn_qaf_is_enabled())
10386 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010387 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010388 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010389 free(adev->snd_dev_ref_cnt);
10390 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010391 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10392 pcm_params_free(adev->use_case_table[i]);
10393 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010394 if (adev->adm_deinit)
10395 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010396 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010397 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010398 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010399 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010400 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010401 if (adev->device_cfg_params) {
10402 free(adev->device_cfg_params);
10403 adev->device_cfg_params = NULL;
10404 }
Derek Chend2530072014-11-24 12:39:14 -080010405 if(adev->ext_hw_plugin)
10406 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010407 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010408 free_map(adev->patch_map);
10409 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010410 free(device);
10411 adev = NULL;
10412 }
10413 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010414 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010415 return 0;
10416}
10417
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010418/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10419 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10420 * just that it _might_ work.
10421 */
10422static int period_size_is_plausible_for_low_latency(int period_size)
10423{
10424 switch (period_size) {
10425 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010426 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010427 case 240:
10428 case 320:
10429 case 480:
10430 return 1;
10431 default:
10432 return 0;
10433 }
10434}
10435
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010436static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10437{
10438 bool is_snd_card_status = false;
10439 bool is_ext_device_status = false;
10440 char value[32];
10441 int card = -1;
10442 card_status_t status;
10443
10444 if (cookie != adev || !parms)
10445 return;
10446
10447 if (!parse_snd_card_status(parms, &card, &status)) {
10448 is_snd_card_status = true;
10449 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10450 is_ext_device_status = true;
10451 } else {
10452 // not a valid event
10453 return;
10454 }
10455
10456 pthread_mutex_lock(&adev->lock);
10457 if (card == adev->snd_card || is_ext_device_status) {
10458 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010459 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010460 adev->card_status = status;
10461 platform_snd_card_update(adev->platform, status);
10462 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010463 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010464 if (status == CARD_STATUS_OFFLINE)
10465 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010466 } else if (is_ext_device_status) {
10467 platform_set_parameters(adev->platform, parms);
10468 }
10469 }
10470 pthread_mutex_unlock(&adev->lock);
10471 return;
10472}
10473
Weiyin Jiang280ea742020-09-08 20:28:22 +080010474/* adev lock held */
10475int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010476{
10477 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010478 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010479 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010480 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481
10482 uc_info = get_usecase_from_list(adev, out->usecase);
10483 if (uc_info == NULL) {
10484 ALOGE("%s: Could not find the usecase (%d) in the list",
10485 __func__, out->usecase);
10486 return -EINVAL;
10487 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010488 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010489
Zhou Songbaddf9f2020-11-20 13:57:39 +080010490 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10491 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010492
10493 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010494 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010495 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010496 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010497 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010498 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10499 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010500
10501 if (is_offload_usecase(out->usecase)) {
10502 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010503 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010504 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10505 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10506 } else {
10507 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010508 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010509 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010510 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010511 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010512 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010513 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010514 // mute stream and switch to speaker if suspended
10515 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010516 assign_devices(&devices, &out->device_list);
10517 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010518 list_for_each(node, &adev->usecase_list) {
10519 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010520 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10521 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010522 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010523 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10524 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010525 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10526 break;
10527 }
10528 }
Zhou Songcf77af02021-05-14 18:21:14 +080010529 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10530 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010531 out->a2dp_muted = true;
10532 if (is_offload_usecase(out->usecase)) {
10533 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10534 compress_pause(out->compr);
10535 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010536 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010537 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10538 out_set_voip_volume(&out->stream, (float)0, (float)0);
10539 else
10540 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10541
Zhou Song8edbbdb2021-01-14 16:48:03 +080010542 /* wait for stale pcm drained before switching to speaker */
10543 uint32_t latency =
10544 (out->config.period_count * out->config.period_size * 1000) /
10545 (out->config.rate);
10546 usleep(latency * 1000);
10547 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010548 }
10549 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010550 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10551 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010552 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010553 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10554 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010555 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010556 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010557 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010558 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010559 }
10560 ALOGV("%s: exit", __func__);
10561 return 0;
10562}
10563
Haynes Mathew George01156f92018-04-13 15:29:54 -070010564void adev_on_battery_status_changed(bool charging)
10565{
10566 pthread_mutex_lock(&adev->lock);
10567 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10568 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010569 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010570 pthread_mutex_unlock(&adev->lock);
10571}
10572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010573static int adev_open(const hw_module_t *module, const char *name,
10574 hw_device_t **device)
10575{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010576 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010577 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010578 char mixer_ctl_name[128] = {0};
10579 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010580
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010581 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010582 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10583
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010584 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010585 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010586 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010587 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010588 ALOGD("%s: returning existing instance of adev", __func__);
10589 ALOGD("%s: exit", __func__);
10590 pthread_mutex_unlock(&adev_init_lock);
10591 return 0;
10592 }
10593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010594 adev = calloc(1, sizeof(struct audio_device));
10595
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010596 if (!adev) {
10597 pthread_mutex_unlock(&adev_init_lock);
10598 return -ENOMEM;
10599 }
10600
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010601 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10602
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010603 // register audio ext hidl at the earliest
10604 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010605#ifdef DYNAMIC_LOG_ENABLED
10606 register_for_dynamic_logging("hal");
10607#endif
10608
Derek Chenf939fb72018-11-13 13:34:41 -080010609 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010610 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010611 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10612 maj_version = atoi(value);
10613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010614 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010615 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010616 adev->device.common.module = (struct hw_module_t *)module;
10617 adev->device.common.close = adev_close;
10618
10619 adev->device.init_check = adev_init_check;
10620 adev->device.set_voice_volume = adev_set_voice_volume;
10621 adev->device.set_master_volume = adev_set_master_volume;
10622 adev->device.get_master_volume = adev_get_master_volume;
10623 adev->device.set_master_mute = adev_set_master_mute;
10624 adev->device.get_master_mute = adev_get_master_mute;
10625 adev->device.set_mode = adev_set_mode;
10626 adev->device.set_mic_mute = adev_set_mic_mute;
10627 adev->device.get_mic_mute = adev_get_mic_mute;
10628 adev->device.set_parameters = adev_set_parameters;
10629 adev->device.get_parameters = adev_get_parameters;
10630 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10631 adev->device.open_output_stream = adev_open_output_stream;
10632 adev->device.close_output_stream = adev_close_output_stream;
10633 adev->device.open_input_stream = adev_open_input_stream;
10634 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010635 adev->device.create_audio_patch = adev_create_audio_patch;
10636 adev->device.release_audio_patch = adev_release_audio_patch;
10637 adev->device.get_audio_port = adev_get_audio_port;
10638 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010639 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010640 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010641
10642 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010643 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010644 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010645 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010646 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010647 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010648 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010649 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010650 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010651 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010652 /* Init audio and voice feature */
10653 audio_extn_feature_init();
10654 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010655 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010656 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010657 list_init(&adev->active_inputs_list);
10658 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010659 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010660 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10661 audio_extn_utils_hash_eq);
10662 if (!adev->io_streams_map) {
10663 ALOGE("%s: Could not create io streams map", __func__);
10664 ret = -ENOMEM;
10665 goto adev_open_err;
10666 }
10667 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10668 audio_extn_utils_hash_eq);
10669 if (!adev->patch_map) {
10670 ALOGE("%s: Could not create audio patch map", __func__);
10671 ret = -ENOMEM;
10672 goto adev_open_err;
10673 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010674 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010675 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010676 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010677 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010678 adev->perf_lock_opts[0] = 0x101;
10679 adev->perf_lock_opts[1] = 0x20E;
10680 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010681 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010682 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010683 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010684 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010685 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010686
Zhou Song68ebc352019-12-05 17:11:15 +080010687 audio_extn_perf_lock_init();
10688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010689 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010690 adev->platform = platform_init(adev);
10691 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010692 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010693 ret = -EINVAL;
10694 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010695 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010696
Aalique Grahame22e49102018-12-18 14:23:57 -080010697 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010698 if (audio_extn_qap_is_enabled()) {
10699 ret = audio_extn_qap_init(adev);
10700 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010701 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010702 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010703 }
10704 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10705 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10706 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010707
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010708 if (audio_extn_qaf_is_enabled()) {
10709 ret = audio_extn_qaf_init(adev);
10710 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010711 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010712 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010713 }
10714
10715 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10716 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10717 }
10718
Derek Chenae7b0342019-02-08 15:17:04 -080010719 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010720 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10721
Eric Laurentc4aef752013-09-12 17:45:53 -070010722 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10723 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10724 if (adev->visualizer_lib == NULL) {
10725 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10726 } else {
10727 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10728 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010729 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010730 "visualizer_hal_start_output");
10731 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010732 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010733 "visualizer_hal_stop_output");
10734 }
10735 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010736 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010737 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010738 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010739 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010740 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010741 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010742
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010743 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10744 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10745 if (adev->offload_effects_lib == NULL) {
10746 ALOGE("%s: DLOPEN failed for %s", __func__,
10747 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10748 } else {
10749 ALOGV("%s: DLOPEN successful for %s", __func__,
10750 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10751 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010752 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010753 "offload_effects_bundle_hal_start_output");
10754 adev->offload_effects_stop_output =
10755 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10756 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010757 adev->offload_effects_set_hpx_state =
10758 (int (*)(bool))dlsym(adev->offload_effects_lib,
10759 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010760 adev->offload_effects_get_parameters =
10761 (void (*)(struct str_parms *, struct str_parms *))
10762 dlsym(adev->offload_effects_lib,
10763 "offload_effects_bundle_get_parameters");
10764 adev->offload_effects_set_parameters =
10765 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10766 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010767 }
10768 }
10769
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010770 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10771 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10772 if (adev->adm_lib == NULL) {
10773 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10774 } else {
10775 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10776 adev->adm_init = (adm_init_t)
10777 dlsym(adev->adm_lib, "adm_init");
10778 adev->adm_deinit = (adm_deinit_t)
10779 dlsym(adev->adm_lib, "adm_deinit");
10780 adev->adm_register_input_stream = (adm_register_input_stream_t)
10781 dlsym(adev->adm_lib, "adm_register_input_stream");
10782 adev->adm_register_output_stream = (adm_register_output_stream_t)
10783 dlsym(adev->adm_lib, "adm_register_output_stream");
10784 adev->adm_deregister_stream = (adm_deregister_stream_t)
10785 dlsym(adev->adm_lib, "adm_deregister_stream");
10786 adev->adm_request_focus = (adm_request_focus_t)
10787 dlsym(adev->adm_lib, "adm_request_focus");
10788 adev->adm_abandon_focus = (adm_abandon_focus_t)
10789 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010790 adev->adm_set_config = (adm_set_config_t)
10791 dlsym(adev->adm_lib, "adm_set_config");
10792 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10793 dlsym(adev->adm_lib, "adm_request_focus_v2");
10794 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10795 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10796 adev->adm_on_routing_change = (adm_on_routing_change_t)
10797 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010798 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10799 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010800 }
10801 }
10802
Aalique Grahame22e49102018-12-18 14:23:57 -080010803 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010804 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010805 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080010806 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010807 //initialize this to false for now,
10808 //this will be set to true through set param
10809 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010810
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010811 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010812 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010813
10814 if (k_enable_extended_precision)
10815 adev_verify_devices(adev);
10816
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010817 adev->dsp_bit_width_enforce_mode =
10818 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010819
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010820 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10821 &adev->streams_output_cfg_list,
10822 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010823
Kiran Kandi910e1862013-10-29 13:29:42 -070010824 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010825
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010826 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010827 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010828 trial = atoi(value);
10829 if (period_size_is_plausible_for_low_latency(trial)) {
10830 pcm_config_low_latency.period_size = trial;
10831 pcm_config_low_latency.start_threshold = trial / 4;
10832 pcm_config_low_latency.avail_min = trial / 4;
10833 configured_low_latency_capture_period_size = trial;
10834 }
10835 }
ronghuiz93177262021-04-21 19:58:13 +080010836 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010837 trial = atoi(value);
10838 if (period_size_is_plausible_for_low_latency(trial)) {
10839 configured_low_latency_capture_period_size = trial;
10840 }
10841 }
10842
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010843 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10844
Eric Laurent4b084132018-10-19 17:33:43 -070010845 adev->camera_orientation = CAMERA_DEFAULT;
10846
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010847 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010848 af_period_multiplier = atoi(value);
10849 if (af_period_multiplier < 0)
10850 af_period_multiplier = 2;
10851 else if (af_period_multiplier > 4)
10852 af_period_multiplier = 4;
10853
10854 ALOGV("new period_multiplier = %d", af_period_multiplier);
10855 }
10856
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010857 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010858
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010859 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010860 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010861 pthread_mutex_unlock(&adev_init_lock);
10862
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010863 if (adev->adm_init)
10864 adev->adm_data = adev->adm_init();
10865
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010866 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010867 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010868
10869 audio_extn_snd_mon_init();
10870 pthread_mutex_lock(&adev->lock);
10871 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10872 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010873 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10874 /*
10875 * if the battery state callback happens before charging can be queried,
10876 * it will be guarded with the adev->lock held in the cb function and so
10877 * the callback value will reflect the latest state
10878 */
10879 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010880 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010881 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010882 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010883 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010884 /* Allocate memory for Device config params */
10885 adev->device_cfg_params = (struct audio_device_config_param*)
10886 calloc(platform_get_max_codec_backend(),
10887 sizeof(struct audio_device_config_param));
10888 if (adev->device_cfg_params == NULL)
10889 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010890
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010891 /*
10892 * Check if new PSPD matrix mixer control is supported. If not
10893 * supported, then set flag so that old mixer ctrl is sent while
10894 * sending pspd coefficients on older kernel version. Query mixer
10895 * control for default pcm id and channel value one.
10896 */
10897 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10898 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10899
10900 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10901 if (!ctl) {
10902 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10903 __func__, mixer_ctl_name);
10904 adev->use_old_pspd_mix_ctrl = true;
10905 }
10906
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010907 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010908 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010909
10910adev_open_err:
10911 free_map(adev->patch_map);
10912 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010913 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010914 pthread_mutex_destroy(&adev->lock);
10915 free(adev);
10916 adev = NULL;
10917 *device = NULL;
10918 pthread_mutex_unlock(&adev_init_lock);
10919 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010920}
10921
10922static struct hw_module_methods_t hal_module_methods = {
10923 .open = adev_open,
10924};
10925
10926struct audio_module HAL_MODULE_INFO_SYM = {
10927 .common = {
10928 .tag = HARDWARE_MODULE_TAG,
10929 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10930 .hal_api_version = HARDWARE_HAL_API_VERSION,
10931 .id = AUDIO_HARDWARE_MODULE_ID,
10932 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010933 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010934 .methods = &hal_module_methods,
10935 },
10936};