blob: eba044bf77e97096fd07fa9d322a90b3611f7ede [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",
Eric Laurentb23d5282013-05-14 15:27:20 -0700431};
432
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700433static const audio_usecase_t offload_usecases[] = {
434 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700435 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
436 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
441 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
442 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700443};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800444
Varun Balaraje49253e2017-07-06 19:48:56 +0530445static const audio_usecase_t interactive_usecases[] = {
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
452 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
453 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
454};
455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456#define STRING_TO_ENUM(string) { #string, string }
457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458struct string_to_enum {
459 const char *name;
460 uint32_t value;
461};
462
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700463static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
470 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800471 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
473 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
474 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
481 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
482 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800483};
484
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700485static const struct string_to_enum formats_name_to_enum_table[] = {
486 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
487 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
488 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700489 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
490 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
491 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700492 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800493 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
494 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700495 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800496};
497
498//list of all supported sample rates by HDMI specification.
499static const int out_hdmi_sample_rates[] = {
500 32000, 44100, 48000, 88200, 96000, 176400, 192000,
501};
502
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700503static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800504 STRING_TO_ENUM(32000),
505 STRING_TO_ENUM(44100),
506 STRING_TO_ENUM(48000),
507 STRING_TO_ENUM(88200),
508 STRING_TO_ENUM(96000),
509 STRING_TO_ENUM(176400),
510 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800511 STRING_TO_ENUM(352800),
512 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700513};
514
Carter Hsu2e429db2019-05-14 18:50:52 +0800515struct in_effect_list {
516 struct listnode list;
517 effect_handle_t handle;
518};
519
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700520static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700521static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700522static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700523//cache last MBDRC cal step level
524static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700525
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530526static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700527static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800528static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530529static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530530
Derek Chen6f293672019-04-01 01:40:24 -0700531static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
532static void in_snd_mon_cb(void * stream, struct str_parms * parms);
533static void out_snd_mon_cb(void * stream, struct str_parms * parms);
534
Zhou Song331c8e52019-08-26 14:16:12 +0800535static int configure_btsco_sample_rate(snd_device_t snd_device);
536
Vatsal Buchac09ae062018-11-14 13:25:08 +0530537#ifdef AUDIO_FEATURE_ENABLED_GCOV
538extern void __gcov_flush();
539static void enable_gcov()
540{
541 __gcov_flush();
542}
543#else
544static void enable_gcov()
545{
546}
547#endif
548
justinweng20fb6d82019-02-21 18:49:00 -0700549static int in_set_microphone_direction(const struct audio_stream_in *stream,
550 audio_microphone_direction_t dir);
551static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
552
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700553static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
554 int flags __unused)
555{
556 int dir = 0;
557 switch (uc_id) {
558 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530559 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700560 dir = 1;
561 case USECASE_AUDIO_PLAYBACK_ULL:
562 break;
563 default:
564 return false;
565 }
566
567 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
568 PCM_PLAYBACK : PCM_CAPTURE);
569 if (adev->adm_is_noirq_avail)
570 return adev->adm_is_noirq_avail(adev->adm_data,
571 adev->snd_card, dev_id, dir);
572 return false;
573}
574
575static void register_out_stream(struct stream_out *out)
576{
577 struct audio_device *adev = out->dev;
578 if (is_offload_usecase(out->usecase) ||
579 !adev->adm_register_output_stream)
580 return;
581
582 // register stream first for backward compatibility
583 adev->adm_register_output_stream(adev->adm_data,
584 out->handle,
585 out->flags);
586
587 if (!adev->adm_set_config)
588 return;
589
590 if (out->realtime)
591 adev->adm_set_config(adev->adm_data,
592 out->handle,
593 out->pcm, &out->config);
594}
595
596static void register_in_stream(struct stream_in *in)
597{
598 struct audio_device *adev = in->dev;
599 if (!adev->adm_register_input_stream)
600 return;
601
602 adev->adm_register_input_stream(adev->adm_data,
603 in->capture_handle,
604 in->flags);
605
606 if (!adev->adm_set_config)
607 return;
608
609 if (in->realtime)
610 adev->adm_set_config(adev->adm_data,
611 in->capture_handle,
612 in->pcm,
613 &in->config);
614}
615
616static void request_out_focus(struct stream_out *out, long ns)
617{
618 struct audio_device *adev = out->dev;
619
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700620 if (adev->adm_request_focus_v2)
621 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, out->handle);
624}
625
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700626static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700627{
628 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700630
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700631 if (adev->adm_request_focus_v2_1)
632 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
633 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700634 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
635 else if (adev->adm_request_focus)
636 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700637
638 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700639}
640
641static void release_out_focus(struct stream_out *out)
642{
643 struct audio_device *adev = out->dev;
644
645 if (adev->adm_abandon_focus)
646 adev->adm_abandon_focus(adev->adm_data, out->handle);
647}
648
649static void release_in_focus(struct stream_in *in)
650{
651 struct audio_device *adev = in->dev;
652 if (adev->adm_abandon_focus)
653 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
654}
655
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530656static int parse_snd_card_status(struct str_parms *parms, int *card,
657 card_status_t *status)
658{
659 char value[32]={0};
660 char state[32]={0};
661
662 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
663 if (ret < 0)
664 return -1;
665
666 // sscanf should be okay as value is of max length 32.
667 // same as sizeof state.
668 if (sscanf(value, "%d,%s", card, state) < 2)
669 return -1;
670
671 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
672 CARD_STATUS_OFFLINE;
673 return 0;
674}
675
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700676static inline void adjust_frames_for_device_delay(struct stream_out *out,
677 uint32_t *dsp_frames) {
678 // Adjustment accounts for A2dp encoder latency with offload usecases
679 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800680 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700681 unsigned long offset =
682 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
683 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
684 }
685}
686
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700687static inline bool free_entry(void *key __unused,
688 void *value, void *context __unused)
689{
690 free(value);
691 return true;
692}
693
694static inline void free_map(Hashmap *map)
695{
696 if (map) {
697 hashmapForEach(map, free_entry, (void *) NULL);
698 hashmapFree(map);
699 }
700}
701
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800702static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703 audio_patch_handle_t patch_handle)
704{
705 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
706 return;
707
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708 struct audio_patch_info *p_info =
709 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
710 if (p_info) {
711 ALOGV("%s: Remove patch %d", __func__, patch_handle);
712 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
713 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700714 free(p_info);
715 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700716}
717
718static inline int io_streams_map_insert(struct audio_device *adev,
719 struct audio_stream *stream,
720 audio_io_handle_t handle,
721 audio_patch_handle_t patch_handle)
722{
723 struct audio_stream_info *s_info =
724 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
725
726 if (s_info == NULL) {
727 ALOGE("%s: Could not allocate stream info", __func__);
728 return -ENOMEM;
729 }
730 s_info->stream = stream;
731 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700732
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *stream_info =
735 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (stream_info != NULL)
737 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800738 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700739 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 return 0;
741}
742
743static inline void io_streams_map_remove(struct audio_device *adev,
744 audio_io_handle_t handle)
745{
746 pthread_mutex_lock(&adev->lock);
747 struct audio_stream_info *s_info =
748 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700749 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800750 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700751 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800752 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700753 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800754done:
755 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700756 return;
757}
758
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800759static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700760 audio_patch_handle_t handle)
761{
762 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700763 p_info = (struct audio_patch_info *)
764 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700765 return p_info;
766}
767
vivek mehtaa76401a2015-04-24 14:12:15 -0700768__attribute__ ((visibility ("default")))
769bool audio_hw_send_gain_dep_calibration(int level) {
770 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700771 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700772
773 pthread_mutex_lock(&adev_init_lock);
774
775 if (adev != NULL && adev->platform != NULL) {
776 pthread_mutex_lock(&adev->lock);
777 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700778
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530779 // cache level info for any of the use case which
780 // was not started.
781 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700782
vivek mehtaa76401a2015-04-24 14:12:15 -0700783 pthread_mutex_unlock(&adev->lock);
784 } else {
785 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
786 }
787
788 pthread_mutex_unlock(&adev_init_lock);
789
790 return ret_val;
791}
792
Ashish Jain5106d362016-05-11 19:23:33 +0530793static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
794{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800795 bool gapless_enabled = false;
796 const char *mixer_ctl_name = "Compress Gapless Playback";
797 struct mixer_ctl *ctl;
798
799 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700800 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530801
802 /*Disable gapless if its AV playback*/
803 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800804
805 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
806 if (!ctl) {
807 ALOGE("%s: Could not get ctl for mixer cmd - %s",
808 __func__, mixer_ctl_name);
809 return -EINVAL;
810 }
811
812 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
813 ALOGE("%s: Could not set gapless mode %d",
814 __func__, gapless_enabled);
815 return -EINVAL;
816 }
817 return 0;
818}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700819
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700820__attribute__ ((visibility ("default")))
821int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
822 int table_size) {
823 int ret_val = 0;
824 ALOGV("%s: enter ... ", __func__);
825
826 pthread_mutex_lock(&adev_init_lock);
827 if (adev == NULL) {
828 ALOGW("%s: adev is NULL .... ", __func__);
829 goto done;
830 }
831
832 pthread_mutex_lock(&adev->lock);
833 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
834 pthread_mutex_unlock(&adev->lock);
835done:
836 pthread_mutex_unlock(&adev_init_lock);
837 ALOGV("%s: exit ... ", __func__);
838 return ret_val;
839}
840
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800841bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800842{
843 bool ret = false;
844 ALOGV("%s: enter ...", __func__);
845
846 pthread_mutex_lock(&adev_init_lock);
847
848 if (adev != NULL && adev->platform != NULL) {
849 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800850 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800851 pthread_mutex_unlock(&adev->lock);
852 }
853
854 pthread_mutex_unlock(&adev_init_lock);
855
856 ALOGV("%s: exit with ret %d", __func__, ret);
857 return ret;
858}
Aalique Grahame22e49102018-12-18 14:23:57 -0800859
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700860static bool is_supported_format(audio_format_t format)
861{
Eric Laurent86e17132013-09-12 17:49:30 -0700862 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530863 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530864 format == AUDIO_FORMAT_AAC_LC ||
865 format == AUDIO_FORMAT_AAC_HE_V1 ||
866 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530867 format == AUDIO_FORMAT_AAC_ADTS_LC ||
868 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
869 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530870 format == AUDIO_FORMAT_AAC_LATM_LC ||
871 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
872 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530873 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
874 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530875 format == AUDIO_FORMAT_PCM_FLOAT ||
876 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700877 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530878 format == AUDIO_FORMAT_AC3 ||
879 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700880 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530881 format == AUDIO_FORMAT_DTS ||
882 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800883 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530884 format == AUDIO_FORMAT_ALAC ||
885 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530886 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530887 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800888 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530889 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700890 format == AUDIO_FORMAT_APTX ||
891 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800892 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700893
894 return false;
895}
896
Kunlei Zhang67cc7072020-12-18 17:16:49 +0800897static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
904 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
905 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
906 return false;
907 }
908 }
909
910 return true;
911}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700912static inline bool is_mmap_usecase(audio_usecase_t uc_id)
913{
914 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800915 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700916 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
917}
918
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700919static inline bool is_valid_volume(float left, float right)
920{
921 return ((left >= 0.0f && right >= 0.0f) ? true : false);
922}
923
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530924static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530925{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530926 ALOGV("%s", __func__);
927 audio_route_apply_and_update_path(adev->audio_route,
928 "asrc-mode");
929 adev->asrc_mode_enabled = true;
930}
931
932static void disable_asrc_mode(struct audio_device *adev)
933{
934 ALOGV("%s", __func__);
935 audio_route_reset_and_update_path(adev->audio_route,
936 "asrc-mode");
937 adev->asrc_mode_enabled = false;
938}
939
Saurav Kumarc1411662020-10-14 10:50:45 +0530940static void check_and_configure_headphone(struct audio_device *adev,
941 struct audio_usecase *uc_info,
942 snd_device_t snd_device)
943{
944 struct listnode *node;
945 struct audio_usecase *usecase;
946 int new_backend_idx, usecase_backend_idx;
947 bool spkr_hph_single_be_native_concurrency;
948
949 new_backend_idx = platform_get_backend_index(snd_device);
950 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
951 if ( spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) {
952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
955 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
956 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
957 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
958 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
959 disable_audio_route(adev, usecase);
960 disable_snd_device(adev, usecase->out_snd_device);
961 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530962 platform_check_and_set_codec_backend_cfg(adev, usecase,
963 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530964 enable_audio_route(adev, usecase);
965 enable_snd_device(adev, usecase->out_snd_device);
966 }
967 }
968 }
969 }
970}
971
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530972/*
973 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
974 * 44.1 or Native DSD backends are enabled for any of current use case.
975 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
976 * - Disable current mix path use case(Headphone backend) and re-enable it with
977 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
978 * e.g. Naitve DSD or Headphone 44.1 -> + 48
979 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530980static void check_and_set_asrc_mode(struct audio_device *adev,
981 struct audio_usecase *uc_info,
982 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530983{
984 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530985 int i, num_new_devices = 0;
986 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
987 /*
988 *Split snd device for new combo use case
989 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
990 */
991 if (platform_split_snd_device(adev->platform,
992 snd_device,
993 &num_new_devices,
994 split_new_snd_devices) == 0) {
995 for (i = 0; i < num_new_devices; i++)
996 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
997 } else {
998 int new_backend_idx = platform_get_backend_index(snd_device);
999 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1000 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1001 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1002 !adev->asrc_mode_enabled) {
1003 struct listnode *node = NULL;
1004 struct audio_usecase *uc = NULL;
1005 struct stream_out *curr_out = NULL;
1006 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1007 int i, num_devices, ret = 0;
1008 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301009
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301010 list_for_each(node, &adev->usecase_list) {
1011 uc = node_to_item(node, struct audio_usecase, list);
1012 curr_out = (struct stream_out*) uc->stream.out;
1013 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1014 /*
1015 *Split snd device for existing combo use case
1016 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1017 */
1018 ret = platform_split_snd_device(adev->platform,
1019 uc->out_snd_device,
1020 &num_devices,
1021 split_snd_devices);
1022 if (ret < 0 || num_devices == 0) {
1023 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1024 split_snd_devices[0] = uc->out_snd_device;
1025 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001026 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301027 for (i = 0; i < num_devices; i++) {
1028 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1029 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1030 if((new_backend_idx == HEADPHONE_BACKEND) &&
1031 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1032 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001033 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301034 __func__);
1035 enable_asrc_mode(adev);
1036 break;
1037 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1038 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1039 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001040 ALOGV("%s: 48K stream detected, disabling and enabling it \
1041 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301042 disable_audio_route(adev, uc);
1043 disable_snd_device(adev, uc->out_snd_device);
1044 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1045 if (new_backend_idx == DSD_NATIVE_BACKEND)
1046 audio_route_apply_and_update_path(adev->audio_route,
1047 "hph-true-highquality-mode");
1048 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1049 (curr_out->bit_width >= 24))
1050 audio_route_apply_and_update_path(adev->audio_route,
1051 "hph-highquality-mode");
1052 enable_asrc_mode(adev);
1053 enable_snd_device(adev, uc->out_snd_device);
1054 enable_audio_route(adev, uc);
1055 break;
1056 }
1057 }
1058 // reset split devices count
1059 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001060 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301061 if (adev->asrc_mode_enabled)
1062 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301063 }
1064 }
1065 }
1066}
1067
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1069 struct audio_effect_config effect_config,
1070 unsigned int param_value)
1071{
1072 char mixer_ctl_name[] = "Audio Effect";
1073 struct mixer_ctl *ctl;
1074 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001075 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001076
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001077 if (in == NULL) {
1078 ALOGE("%s: active input stream is NULL", __func__);
1079 return -EINVAL;
1080 }
1081
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001082 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1083 if (!ctl) {
1084 ALOGE("%s: Could not get mixer ctl - %s",
1085 __func__, mixer_ctl_name);
1086 return -EINVAL;
1087 }
1088
1089 set_values[0] = 1; //0:Rx 1:Tx
1090 set_values[1] = in->app_type_cfg.app_type;
1091 set_values[2] = (long)effect_config.module_id;
1092 set_values[3] = (long)effect_config.instance_id;
1093 set_values[4] = (long)effect_config.param_id;
1094 set_values[5] = param_value;
1095
1096 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1097
1098 return 0;
1099
1100}
1101
1102static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1103 int effect_type, unsigned int *param_value)
1104{
1105 int ret = 0;
1106 struct audio_effect_config other_effect_config;
1107 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001108 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001109
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001110 if (in == NULL) {
1111 ALOGE("%s: active input stream is NULL", __func__);
1112 return -EINVAL;
1113 }
1114
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001115 usecase = get_usecase_from_list(adev, in->usecase);
1116 if (!usecase)
1117 return -EINVAL;
1118
1119 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1120 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1121 if (ret < 0) {
1122 ALOGE("%s Failed to get effect params %d", __func__, ret);
1123 return ret;
1124 }
1125
1126 if (module_id == other_effect_config.module_id) {
1127 //Same module id for AEC/NS. Values need to be combined
1128 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1129 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1130 *param_value |= other_effect_config.param_value;
1131 }
1132 }
1133
1134 return ret;
1135}
1136
1137static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301138{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001139 struct audio_effect_config effect_config;
1140 struct audio_usecase *usecase = NULL;
1141 int ret = 0;
1142 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001143 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001144
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001145 if(!voice_extn_is_dynamic_ecns_enabled())
1146 return ENOSYS;
1147
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001148 if (!in) {
1149 ALOGE("%s: Invalid input stream", __func__);
1150 return -EINVAL;
1151 }
1152
1153 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1154
1155 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001156 if (usecase == NULL) {
1157 ALOGE("%s: Could not find the usecase (%d) in the list",
1158 __func__, in->usecase);
1159 return -EINVAL;
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161
1162 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1163 if (ret < 0) {
1164 ALOGE("%s Failed to get module id %d", __func__, ret);
1165 return ret;
1166 }
1167 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1168 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1169
1170 if(enable)
1171 param_value = effect_config.param_value;
1172
1173 /*Special handling for AEC & NS effects Param values need to be
1174 updated if module ids are same*/
1175
1176 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1177 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1178 if (ret < 0)
1179 return ret;
1180 }
1181
1182 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1183
1184 return ret;
1185}
1186
1187static void check_and_enable_effect(struct audio_device *adev)
1188{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001189 if(!voice_extn_is_dynamic_ecns_enabled())
1190 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001191
Eric Laurent637e2d42018-11-15 12:24:31 -08001192 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001193
Eric Laurent637e2d42018-11-15 12:24:31 -08001194 if (in != NULL && !in->standby) {
1195 if (in->enable_aec)
1196 enable_disable_effect(adev, EFFECT_AEC, true);
1197
1198 if (in->enable_ns &&
1199 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1200 enable_disable_effect(adev, EFFECT_NS, true);
1201 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001202 }
1203}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001205int pcm_ioctl(struct pcm *pcm, int request, ...)
1206{
1207 va_list ap;
1208 void * arg;
1209 int pcm_fd = *(int*)pcm;
1210
1211 va_start(ap, request);
1212 arg = va_arg(ap, void *);
1213 va_end(ap);
1214
1215 return ioctl(pcm_fd, request, arg);
1216}
1217
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001218int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001219 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001221 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001222 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301223 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301224 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001225 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301226 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001227
1228 if (usecase == NULL)
1229 return -EINVAL;
1230
1231 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1232
Carter Hsu2e429db2019-05-14 18:50:52 +08001233 if (usecase->type == PCM_CAPTURE) {
1234 struct stream_in *in = usecase->stream.in;
1235 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001237
1238 if (in) {
1239 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001240 list_init(&out_devices);
1241 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001242 struct listnode *node;
1243 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1244 USECASE_AUDIO_PLAYBACK_VOIP);
1245 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001246 assign_devices(&out_devices,
1247 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001248 } else if (adev->primary_output &&
1249 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001250 assign_devices(&out_devices,
1251 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001252 } else {
1253 list_for_each(node, &adev->usecase_list) {
1254 uinfo = node_to_item(node, struct audio_usecase, list);
1255 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001256 assign_devices(&out_devices,
1257 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001258 break;
1259 }
1260 }
1261 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001262
1263 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001264 in->ec_opened = true;
1265 }
1266 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001267 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1268 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1269 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001270 snd_device = usecase->in_snd_device;
1271 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001273 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001274
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001275#ifdef DS1_DOLBY_DAP_ENABLED
1276 audio_extn_dolby_set_dmid(adev);
1277 audio_extn_dolby_set_endpoint(adev);
1278#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001279 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001280 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301281 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001282 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001283 if (audio_extn_is_maxx_audio_enabled())
1284 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301285 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001286 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1287 out = usecase->stream.out;
1288 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301289 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1290 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301291
1292 if (usecase->type == PCM_CAPTURE) {
1293 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001294 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301295 ALOGD("%s: set custom mtmx params v1", __func__);
1296 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1297 }
1298 } else {
1299 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1300 }
Manish Dewangan58229382017-02-02 15:48:41 +05301301
Andy Hung756ecc12018-10-19 17:47:12 -07001302 // we shouldn't truncate mixer_path
1303 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1304 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1305 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001306 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001307 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301308 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1309 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1310 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1311 if (parms) {
1312 audio_extn_fm_set_parameters(adev, parms);
1313 str_parms_destroy(parms);
1314 }
1315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316 ALOGV("%s: exit", __func__);
1317 return 0;
1318}
1319
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001320int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001321 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001324 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301325 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001326
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301327 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001328 return -EINVAL;
1329
1330 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301331 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001332 snd_device = usecase->in_snd_device;
1333 else
1334 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001335
1336 /* disable island and power mode on supported device for voice call */
1337 if (usecase->type == VOICE_CALL) {
1338 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1339 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1340 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1341 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1342 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1343 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001344 if (voice_is_lte_call_active(adev))
1345 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001346 ALOGD("%s: disable island cfg and power mode in voice tx path",
1347 __func__);
1348 }
1349 }
1350 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1351 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1352 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1353 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1354 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1355 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1356 ALOGD("%s: disable island cfg and power mode in voice rx path",
1357 __func__);
1358 }
1359 }
1360 }
1361
Andy Hung756ecc12018-10-19 17:47:12 -07001362 // we shouldn't truncate mixer_path
1363 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1364 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1365 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001366 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001367 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001368 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001369 if (usecase->type == PCM_CAPTURE) {
1370 struct stream_in *in = usecase->stream.in;
1371 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001372 struct listnode out_devices;
1373 list_init(&out_devices);
1374 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001375 in->ec_opened = false;
1376 }
1377 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001378 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301379 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301380
1381 if (usecase->type == PCM_CAPTURE) {
1382 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001383 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301384 ALOGD("%s: reset custom mtmx params v1", __func__);
1385 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1386 }
1387 } else {
1388 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1389 }
1390
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001391 if ((usecase->type == PCM_PLAYBACK) &&
1392 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301393 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 ALOGV("%s: exit", __func__);
1396 return 0;
1397}
1398
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001399int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301402 int i, num_devices = 0;
1403 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001404 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1405
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001406 if (snd_device < SND_DEVICE_MIN ||
1407 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001408 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001409 return -EINVAL;
1410 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001412 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001413 ALOGE("%s: Invalid sound device returned", __func__);
1414 return -EINVAL;
1415 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001416
1417 adev->snd_dev_ref_cnt[snd_device]++;
1418
1419 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1420 (platform_split_snd_device(adev->platform,
1421 snd_device,
1422 &num_devices,
1423 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001424 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001425 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001426 /* Set backend config for A2DP to ensure slimbus configuration
1427 is correct if A2DP is already active and backend is closed
1428 and re-opened */
1429 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1430 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 return 0;
1432 }
1433
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001434 if (audio_extn_spkr_prot_is_enabled())
1435 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001436
Aalique Grahame22e49102018-12-18 14:23:57 -08001437 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1438
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001439 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1440 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001441 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1442 goto err;
1443 }
1444 audio_extn_dev_arbi_acquire(snd_device);
1445 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001446 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001447 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001448 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001449 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001450 } else if (platform_split_snd_device(adev->platform,
1451 snd_device,
1452 &num_devices,
1453 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301454 for (i = 0; i < num_devices; i++) {
1455 enable_snd_device(adev, new_snd_devices[i]);
1456 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001457 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001458 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001459 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301460
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001461 /* enable island and power mode on supported device */
1462 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1463 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1464 platform_set_island_cfg_on_device(adev, snd_device, true);
1465 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001466 if (voice_is_lte_call_active(adev) &&
1467 (snd_device >= SND_DEVICE_IN_BEGIN &&
1468 snd_device < SND_DEVICE_IN_END))
1469 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001470 ALOGD("%s: enable island cfg and power mode on: %s",
1471 __func__, device_name);
1472 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301473
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301474 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1475 if (audio_extn_a2dp_start_playback() < 0) {
1476 ALOGE(" fail to configure A2dp Source control path ");
1477 goto err;
1478 } else {
1479 adev->a2dp_started = true;
1480 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001481 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001482
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001483 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1484 (audio_extn_a2dp_start_capture() < 0)) {
1485 ALOGE(" fail to configure A2dp Sink control path ");
1486 goto err;
1487 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301488
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001489 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1490 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1491 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1492 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1493 ALOGE(" fail to configure sco control path ");
1494 goto err;
1495 }
Zhou Song12c29502019-03-16 10:37:18 +08001496 }
1497
Zhou Song331c8e52019-08-26 14:16:12 +08001498 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001499 /* due to the possibility of calibration overwrite between listen
1500 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001501 audio_extn_sound_trigger_update_device_status(snd_device,
1502 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301503 audio_extn_listen_update_device_status(snd_device,
1504 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001505 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001506 audio_extn_sound_trigger_update_device_status(snd_device,
1507 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301508 audio_extn_listen_update_device_status(snd_device,
1509 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001510 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001511 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001512 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001513 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301514
1515 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1516 !adev->native_playback_enabled &&
1517 audio_is_true_native_stream_active(adev)) {
1518 ALOGD("%s: %d: napb: enabling native mode in hardware",
1519 __func__, __LINE__);
1520 audio_route_apply_and_update_path(adev->audio_route,
1521 "true-native-mode");
1522 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301523 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301524 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1525 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001526 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001527 ALOGD("%s: init ec ref loopback", __func__);
1528 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532err:
1533 adev->snd_dev_ref_cnt[snd_device]--;
1534 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535}
1536
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001537int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001538 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301540 int i, num_devices = 0;
1541 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001542 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1543
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001544 if (snd_device < SND_DEVICE_MIN ||
1545 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001546 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001547 return -EINVAL;
1548 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001549
1550 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1551 ALOGE("%s: Invalid sound device returned", __func__);
1552 return -EINVAL;
1553 }
1554
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1556 ALOGE("%s: device ref cnt is already 0", __func__);
1557 return -EINVAL;
1558 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001559
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001561
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001564 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301565
Aalique Grahame22e49102018-12-18 14:23:57 -08001566 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1567
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001568 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1569 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001570 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001571
1572 // when speaker device is disabled, reset swap.
1573 // will be renabled on usecase start
1574 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001575 } else if (platform_split_snd_device(adev->platform,
1576 snd_device,
1577 &num_devices,
1578 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301579 for (i = 0; i < num_devices; i++) {
1580 disable_snd_device(adev, new_snd_devices[i]);
1581 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001582 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001583 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001584 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001585 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001586
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301587 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301588 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301589 adev->a2dp_started = false;
1590 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001591 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001592 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001593 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301594 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001595 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301596 adev->native_playback_enabled) {
1597 ALOGD("%s: %d: napb: disabling native mode in hardware",
1598 __func__, __LINE__);
1599 audio_route_reset_and_update_path(adev->audio_route,
1600 "true-native-mode");
1601 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001602 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301603 adev->asrc_mode_enabled) {
1604 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301605 disable_asrc_mode(adev);
1606 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001607 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301608 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001609 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001610 ALOGD("%s: deinit ec ref loopback", __func__);
1611 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1612 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001613
1614 audio_extn_utils_release_snd_device(snd_device);
1615 } else {
1616 if (platform_split_snd_device(adev->platform,
1617 snd_device,
1618 &num_devices,
1619 new_snd_devices) == 0) {
1620 for (i = 0; i < num_devices; i++) {
1621 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1622 }
1623 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 return 0;
1627}
1628
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001629/*
1630 legend:
1631 uc - existing usecase
1632 new_uc - new usecase
1633 d1, d11, d2 - SND_DEVICE enums
1634 a1, a2 - corresponding ANDROID device enums
1635 B1, B2 - backend strings
1636
1637case 1
1638 uc->dev d1 (a1) B1
1639 new_uc->dev d1 (a1), d2 (a2) B1, B2
1640
1641 resolution: disable and enable uc->dev on d1
1642
1643case 2
1644 uc->dev d1 (a1) B1
1645 new_uc->dev d11 (a1) B1
1646
1647 resolution: need to switch uc since d1 and d11 are related
1648 (e.g. speaker and voice-speaker)
1649 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1650
1651case 3
1652 uc->dev d1 (a1) B1
1653 new_uc->dev d2 (a2) B2
1654
1655 resolution: no need to switch uc
1656
1657case 4
1658 uc->dev d1 (a1) B1
1659 new_uc->dev d2 (a2) B1
1660
1661 resolution: disable enable uc-dev on d2 since backends match
1662 we cannot enable two streams on two different devices if they
1663 share the same backend. e.g. if offload is on speaker device using
1664 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1665 using the same backend, offload must also be switched to voice-handset.
1666
1667case 5
1668 uc->dev d1 (a1) B1
1669 new_uc->dev d1 (a1), d2 (a2) B1
1670
1671 resolution: disable enable uc-dev on d2 since backends match
1672 we cannot enable two streams on two different devices if they
1673 share the same backend.
1674
1675case 6
1676 uc->dev d1 (a1) B1
1677 new_uc->dev d2 (a1) B2
1678
1679 resolution: no need to switch
1680
1681case 7
1682 uc->dev d1 (a1), d2 (a2) B1, B2
1683 new_uc->dev d1 (a1) B1
1684
1685 resolution: no need to switch
1686
Zhou Song4ba65882018-07-09 14:48:07 +08001687case 8
1688 uc->dev d1 (a1) B1
1689 new_uc->dev d11 (a1), d2 (a2) B1, B2
1690 resolution: compared to case 1, for this case, d1 and d11 are related
1691 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301692
1693case 9
1694 uc->dev d1 (a1), d2(a2) B1 B2
1695 new_uc->dev d1 (a1), d22 (a2) B1, B2
1696 resolution: disable enable uc-dev on d2 since backends match
1697 we cannot enable two streams on two different devices if they
1698 share the same backend. This is special case for combo use case
1699 with a2dp and sco devices which uses same backend.
1700 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701*/
1702static snd_device_t derive_playback_snd_device(void * platform,
1703 struct audio_usecase *uc,
1704 struct audio_usecase *new_uc,
1705 snd_device_t new_snd_device)
1706{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001707 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001708
1709 snd_device_t d1 = uc->out_snd_device;
1710 snd_device_t d2 = new_snd_device;
1711
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001712 list_init(&a1);
1713 list_init(&a2);
1714
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301715 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301716 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001717 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1718 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301719 break;
1720 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001721 assign_devices(&a1, &uc->stream.out->device_list);
1722 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301723 break;
1724 }
1725
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001726 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001727 if (!compare_devices(&a1, &a2) &&
1728 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001729 snd_device_t d3[2];
1730 int num_devices = 0;
1731 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001732 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001733 &num_devices,
1734 d3);
1735 if (ret < 0) {
1736 if (ret != -ENOSYS) {
1737 ALOGW("%s failed to split snd_device %d",
1738 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001739 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001740 }
1741 goto end;
1742 }
1743
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001744 if (platform_check_backends_match(d3[0], d3[1])) {
1745 return d2; // case 5
1746 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301747 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1748 platform_check_backends_match(d1, d2))
1749 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001750 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301751 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001752 // check if d1 is related to any of d3's
1753 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001754 return d1; // case 1
1755 else
1756 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001757 }
1758 } else {
1759 if (platform_check_backends_match(d1, d2)) {
1760 return d2; // case 2, 4
1761 } else {
1762 return d1; // case 6, 3
1763 }
1764 }
1765
1766end:
1767 return d2; // return whatever was calculated before.
1768}
1769
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301771 struct audio_usecase *uc_info,
1772 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773{
1774 struct listnode *node;
1775 struct audio_usecase *usecase;
1776 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301777 snd_device_t uc_derive_snd_device;
1778 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001779 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1780 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001781 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301782 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001783 /*
1784 * This function is to make sure that all the usecases that are active on
1785 * the hardware codec backend are always routed to any one device that is
1786 * handled by the hardware codec.
1787 * For example, if low-latency and deep-buffer usecases are currently active
1788 * on speaker and out_set_parameters(headset) is received on low-latency
1789 * output, then we have to make sure deep-buffer is also switched to headset,
1790 * because of the limitation that both the devices cannot be enabled
1791 * at the same time as they share the same backend.
1792 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001793 /*
1794 * This call is to check if we need to force routing for a particular stream
1795 * If there is a backend configuration change for the device when a
1796 * new stream starts, then ADM needs to be closed and re-opened with the new
1797 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001798 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001799 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001800 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1801 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301802 /* For a2dp device reconfigure all active sessions
1803 * with new AFE encoder format based on a2dp state
1804 */
1805 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301806 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1807 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301808 audio_extn_a2dp_is_force_device_switch()) {
1809 force_routing = true;
1810 force_restart_session = true;
1811 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001812
1813 /*
1814 * Island cfg and power mode config needs to set before AFE port start.
1815 * Set force routing in case of voice device was enable before.
1816 */
1817 if (uc_info->type == VOICE_CALL &&
1818 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001819 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001820 platform_check_and_update_island_power_status(adev->platform,
1821 uc_info,
1822 snd_device)) {
1823 force_routing = true;
1824 ALOGD("%s:becf: force routing %d for power mode supported device",
1825 __func__, force_routing);
1826 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301827 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001830 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001831 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1833 switch_device[i] = false;
1834
1835 list_for_each(node, &adev->usecase_list) {
1836 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001837
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301838 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1839 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301840 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301841 platform_get_snd_device_name(usecase->out_snd_device),
1842 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301843 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1844 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301845 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1846 usecase, uc_info, snd_device);
1847 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001848 (is_codec_backend_out_device_type(&usecase->device_list) ||
1849 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1850 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1851 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1852 is_a2dp_out_device_type(&usecase->device_list) ||
1853 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301854 ((force_restart_session) ||
1855 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301856 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1857 __func__, use_case_table[usecase->id],
1858 platform_get_snd_device_name(usecase->out_snd_device));
1859 disable_audio_route(adev, usecase);
1860 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301861 /* Enable existing usecase on derived playback device */
1862 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301863 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301864 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001865 }
1866 }
1867
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301868 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1869 num_uc_to_switch);
1870
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001871 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001872 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301874 /* Make sure the previous devices to be disabled first and then enable the
1875 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 list_for_each(node, &adev->usecase_list) {
1877 usecase = node_to_item(node, struct audio_usecase, list);
1878 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001879 /* Check if output sound device to be switched can be split and if any
1880 of the split devices match with derived sound device */
1881 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1882 &num_devices, split_snd_devices) == 0) {
1883 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1884 for (i = 0; i < num_devices; i++) {
1885 /* Disable devices that do not match with derived sound device */
1886 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1887 disable_snd_device(adev, split_snd_devices[i]);
1888 }
1889 } else {
1890 disable_snd_device(adev, usecase->out_snd_device);
1891 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001892 }
1893 }
1894
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001895 list_for_each(node, &adev->usecase_list) {
1896 usecase = node_to_item(node, struct audio_usecase, list);
1897 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001898 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1899 &num_devices, split_snd_devices) == 0) {
1900 /* Enable derived sound device only if it does not match with
1901 one of the split sound devices. This is because the matching
1902 sound device was not disabled */
1903 bool should_enable = true;
1904 for (i = 0; i < num_devices; i++) {
1905 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1906 should_enable = false;
1907 break;
1908 }
1909 }
1910 if (should_enable)
1911 enable_snd_device(adev, derive_snd_device[usecase->id]);
1912 } else {
1913 enable_snd_device(adev, derive_snd_device[usecase->id]);
1914 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001915 }
1916 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001917
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 /* Re-route all the usecases on the shared backend other than the
1919 specified usecase to new snd devices */
1920 list_for_each(node, &adev->usecase_list) {
1921 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301922 /* Update the out_snd_device only before enabling the audio route */
1923 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301924 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301925 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1926 use_case_table[usecase->id],
1927 platform_get_snd_device_name(usecase->out_snd_device));
1928 /* Update voc calibration before enabling Voice/VoIP route */
1929 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1930 status = platform_switch_voice_call_device_post(adev->platform,
1931 usecase->out_snd_device,
1932 platform_get_input_snd_device(
1933 adev->platform, NULL,
1934 &uc_info->device_list,
1935 usecase->type));
1936 enable_audio_route(adev, usecase);
1937 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1938 out_set_voip_volume(&usecase->stream.out->stream,
1939 usecase->stream.out->volume_l,
1940 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301941 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001942 }
1943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001944 }
1945}
1946
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301947static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001948 struct audio_usecase *uc_info,
1949 snd_device_t snd_device)
1950{
1951 struct listnode *node;
1952 struct audio_usecase *usecase;
1953 bool switch_device[AUDIO_USECASE_MAX];
1954 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001955 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001956 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001957
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301958 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1959 snd_device);
1960 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301961
1962 /*
1963 * Make sure out devices is checked against out codec backend device and
1964 * also in devices against in codec backend. Checking out device against in
1965 * codec backend or vice versa causes issues.
1966 */
1967 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001968 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001969
1970 /*
1971 * Island cfg and power mode config needs to set before AFE port start.
1972 * Set force routing in case of voice device was enable before.
1973 */
1974
1975 if (uc_info->type == VOICE_CALL &&
1976 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001977 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001978 platform_check_and_update_island_power_status(adev->platform,
1979 uc_info,
1980 snd_device)) {
1981 force_routing = true;
1982 ALOGD("%s:becf: force routing %d for power mode supported device",
1983 __func__, force_routing);
1984 }
1985
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001986 /*
1987 * This function is to make sure that all the active capture usecases
1988 * are always routed to the same input sound device.
1989 * For example, if audio-record and voice-call usecases are currently
1990 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1991 * is received for voice call then we have to make sure that audio-record
1992 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1993 * because of the limitation that two devices cannot be enabled
1994 * at the same time if they share the same backend.
1995 */
1996 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1997 switch_device[i] = false;
1998
1999 list_for_each(node, &adev->usecase_list) {
2000 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302001 /*
2002 * TODO: Enhance below condition to handle BT sco/USB multi recording
2003 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302004
2005 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2006 (usecase->in_snd_device != snd_device || force_routing));
2007 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2008 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2009 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002010 ((backend_check_cond &&
2011 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002012 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002013 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002014 is_single_device_type_equal(&usecase->device_list,
2015 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002016 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002017 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002018 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302019 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002020 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002021 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002022 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002023 switch_device[usecase->id] = true;
2024 num_uc_to_switch++;
2025 }
2026 }
2027
2028 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002029 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002030
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302031 /* Make sure the previous devices to be disabled first and then enable the
2032 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002033 list_for_each(node, &adev->usecase_list) {
2034 usecase = node_to_item(node, struct audio_usecase, list);
2035 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002036 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002037 }
2038 }
2039
2040 list_for_each(node, &adev->usecase_list) {
2041 usecase = node_to_item(node, struct audio_usecase, list);
2042 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002043 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002044 }
2045 }
2046
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002047 /* Re-route all the usecases on the shared backend other than the
2048 specified usecase to new snd devices */
2049 list_for_each(node, &adev->usecase_list) {
2050 usecase = node_to_item(node, struct audio_usecase, list);
2051 /* Update the in_snd_device only before enabling the audio route */
2052 if (switch_device[usecase->id] ) {
2053 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302054 /* Update voc calibration before enabling Voice/VoIP route */
2055 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2056 snd_device_t voip_snd_device;
2057 voip_snd_device = platform_get_output_snd_device(adev->platform,
2058 usecase->stream.out,
2059 usecase->type);
2060 status = platform_switch_voice_call_device_post(adev->platform,
2061 voip_snd_device,
2062 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002063 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302064 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002065 }
2066 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002067 }
2068}
2069
Mingming Yin3a941d42016-02-17 18:08:05 -08002070static void reset_hdmi_sink_caps(struct stream_out *out) {
2071 int i = 0;
2072
2073 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2074 out->supported_channel_masks[i] = 0;
2075 }
2076 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2077 out->supported_formats[i] = 0;
2078 }
2079 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2080 out->supported_sample_rates[i] = 0;
2081 }
2082}
2083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002085static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086{
Mingming Yin3a941d42016-02-17 18:08:05 -08002087 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002088 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2089 out->extconn.cs.controller,
2090 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091
Mingming Yin3a941d42016-02-17 18:08:05 -08002092 reset_hdmi_sink_caps(out);
2093
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002094 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002095 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002096 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002097 out->extconn.cs.stream);
2098 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002099 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002100 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002101 }
2102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002105 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002106 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002107 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2108 case 6:
2109 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2110 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2111 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2112 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2113 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2114 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 break;
2116 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002117 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002118 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 break;
2120 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002121
2122 // check channel format caps
2123 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002124 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2125 out->extconn.cs.controller,
2126 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002127 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2128 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2129 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2130 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2131 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2132 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2133 }
2134
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002135 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2136 out->extconn.cs.controller,
2137 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002138 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2139 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2140 }
2141
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002142 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2143 out->extconn.cs.controller,
2144 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002145 ALOGV(":%s HDMI supports DTS format", __func__);
2146 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2147 }
2148
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002149 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2150 out->extconn.cs.controller,
2151 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002152 ALOGV(":%s HDMI supports DTS HD format", __func__);
2153 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2154 }
2155
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002156 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2157 out->extconn.cs.controller,
2158 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002159 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2160 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2161 }
2162
Mingming Yin3a941d42016-02-17 18:08:05 -08002163
2164 // check sample rate caps
2165 i = 0;
2166 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002167 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2168 out->extconn.cs.controller,
2169 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002170 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2171 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2172 }
2173 }
2174
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002175 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176}
2177
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002178static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2179 uint32_t *supported_sample_rates __unused,
2180 uint32_t max_rates __unused)
2181{
2182 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2183 supported_sample_rates,
2184 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302185 ssize_t i = 0;
2186
2187 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002188 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2189 supported_sample_rates[i]);
2190 }
2191 return count;
2192}
2193
2194static inline int read_usb_sup_channel_masks(bool is_playback,
2195 audio_channel_mask_t *supported_channel_masks,
2196 uint32_t max_masks)
2197{
2198 int channels = audio_extn_usb_get_max_channels(is_playback);
2199 int channel_count;
2200 uint32_t num_masks = 0;
2201 if (channels > MAX_HIFI_CHANNEL_COUNT)
2202 channels = MAX_HIFI_CHANNEL_COUNT;
2203
2204 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002205 // start from 2 channels as framework currently doesn't support mono.
2206 if (channels >= FCC_2) {
2207 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2208 }
2209 for (channel_count = FCC_2;
2210 channel_count <= channels && num_masks < max_masks;
2211 ++channel_count) {
2212 supported_channel_masks[num_masks++] =
2213 audio_channel_mask_for_index_assignment_from_count(channel_count);
2214 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002215 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002216 // For capture we report all supported channel masks from 1 channel up.
2217 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002218 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2219 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002220 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2221 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2222 if (channel_count <= FCC_2) {
2223 mask = audio_channel_in_mask_from_count(channel_count);
2224 supported_channel_masks[num_masks++] = mask;
2225 }
2226 const audio_channel_mask_t index_mask =
2227 audio_channel_mask_for_index_assignment_from_count(channel_count);
2228 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2229 supported_channel_masks[num_masks++] = index_mask;
2230 }
2231 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002232 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302233
vincenttewf51c94e2019-05-07 10:28:53 +08002234 for (size_t i = 0; i < num_masks; ++i) {
2235 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2236 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302237 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002238 return num_masks;
2239}
2240
2241static inline int read_usb_sup_formats(bool is_playback __unused,
2242 audio_format_t *supported_formats,
2243 uint32_t max_formats __unused)
2244{
2245 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2246 switch (bitwidth) {
2247 case 24:
2248 // XXX : usb.c returns 24 for s24 and s24_le?
2249 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2250 break;
2251 case 32:
2252 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2253 break;
2254 case 16:
2255 default :
2256 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2257 break;
2258 }
2259 ALOGV("%s: %s supported format %d", __func__,
2260 is_playback ? "P" : "C", bitwidth);
2261 return 1;
2262}
2263
2264static inline int read_usb_sup_params_and_compare(bool is_playback,
2265 audio_format_t *format,
2266 audio_format_t *supported_formats,
2267 uint32_t max_formats,
2268 audio_channel_mask_t *mask,
2269 audio_channel_mask_t *supported_channel_masks,
2270 uint32_t max_masks,
2271 uint32_t *rate,
2272 uint32_t *supported_sample_rates,
2273 uint32_t max_rates) {
2274 int ret = 0;
2275 int num_formats;
2276 int num_masks;
2277 int num_rates;
2278 int i;
2279
2280 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2281 max_formats);
2282 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2283 max_masks);
2284
2285 num_rates = read_usb_sup_sample_rates(is_playback,
2286 supported_sample_rates, max_rates);
2287
2288#define LUT(table, len, what, dflt) \
2289 for (i=0; i<len && (table[i] != what); i++); \
2290 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2291
2292 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2293 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2294 LUT(supported_sample_rates, num_rates, *rate, 0);
2295
2296#undef LUT
2297 return ret < 0 ? -EINVAL : 0; // HACK TBD
2298}
2299
Alexy Josephb1379942016-01-29 15:49:38 -08002300audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002301 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002302{
2303 struct audio_usecase *usecase;
2304 struct listnode *node;
2305
2306 list_for_each(node, &adev->usecase_list) {
2307 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002308 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002309 ALOGV("%s: usecase id %d", __func__, usecase->id);
2310 return usecase->id;
2311 }
2312 }
2313 return USECASE_INVALID;
2314}
2315
Alexy Josephb1379942016-01-29 15:49:38 -08002316struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002317 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002318{
2319 struct audio_usecase *usecase;
2320 struct listnode *node;
2321
2322 list_for_each(node, &adev->usecase_list) {
2323 usecase = node_to_item(node, struct audio_usecase, list);
2324 if (usecase->id == uc_id)
2325 return usecase;
2326 }
2327 return NULL;
2328}
2329
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302330/*
2331 * is a true native playback active
2332 */
2333bool audio_is_true_native_stream_active(struct audio_device *adev)
2334{
2335 bool active = false;
2336 int i = 0;
2337 struct listnode *node;
2338
2339 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2340 ALOGV("%s:napb: not in true mode or non hdphones device",
2341 __func__);
2342 active = false;
2343 goto exit;
2344 }
2345
2346 list_for_each(node, &adev->usecase_list) {
2347 struct audio_usecase *uc;
2348 uc = node_to_item(node, struct audio_usecase, list);
2349 struct stream_out *curr_out =
2350 (struct stream_out*) uc->stream.out;
2351
2352 if (curr_out && PCM_PLAYBACK == uc->type) {
2353 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2354 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2355 uc->id, curr_out->sample_rate,
2356 curr_out->bit_width,
2357 platform_get_snd_device_name(uc->out_snd_device));
2358
2359 if (is_offload_usecase(uc->id) &&
2360 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2361 active = true;
2362 ALOGD("%s:napb:native stream detected", __func__);
2363 }
2364 }
2365 }
2366exit:
2367 return active;
2368}
2369
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002370uint32_t adev_get_dsp_bit_width_enforce_mode()
2371{
2372 if (adev == NULL) {
2373 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2374 return 0;
2375 }
2376 return adev->dsp_bit_width_enforce_mode;
2377}
2378
2379static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2380{
2381 char value[PROPERTY_VALUE_MAX];
2382 int trial;
2383 uint32_t dsp_bit_width_enforce_mode = 0;
2384
2385 if (!mixer) {
2386 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2387 __func__);
2388 return 0;
2389 }
2390
2391 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2392 value, NULL) > 0) {
2393 trial = atoi(value);
2394 switch (trial) {
2395 case 16:
2396 dsp_bit_width_enforce_mode = 16;
2397 break;
2398 case 24:
2399 dsp_bit_width_enforce_mode = 24;
2400 break;
2401 case 32:
2402 dsp_bit_width_enforce_mode = 32;
2403 break;
2404 default:
2405 dsp_bit_width_enforce_mode = 0;
2406 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2407 break;
2408 }
2409 }
2410
2411 return dsp_bit_width_enforce_mode;
2412}
2413
2414static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2415 uint32_t enforce_mode,
2416 bool enable)
2417{
2418 struct mixer_ctl *ctl = NULL;
2419 const char *mixer_ctl_name = "ASM Bit Width";
2420 uint32_t asm_bit_width_mode = 0;
2421
2422 if (enforce_mode == 0) {
2423 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2424 return;
2425 }
2426
2427 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2428 if (!ctl) {
2429 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2430 __func__, mixer_ctl_name);
2431 return;
2432 }
2433
2434 if (enable)
2435 asm_bit_width_mode = enforce_mode;
2436 else
2437 asm_bit_width_mode = 0;
2438
2439 ALOGV("%s DSP bit width feature status is %d width=%d",
2440 __func__, enable, asm_bit_width_mode);
2441 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2442 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2443 asm_bit_width_mode);
2444
2445 return;
2446}
2447
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302448/*
2449 * if native DSD playback active
2450 */
2451bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2452{
2453 bool active = false;
2454 struct listnode *node = NULL;
2455 struct audio_usecase *uc = NULL;
2456 struct stream_out *curr_out = NULL;
2457
2458 list_for_each(node, &adev->usecase_list) {
2459 uc = node_to_item(node, struct audio_usecase, list);
2460 curr_out = (struct stream_out*) uc->stream.out;
2461
2462 if (curr_out && PCM_PLAYBACK == uc->type &&
2463 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2464 active = true;
2465 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302466 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302467 }
2468 }
2469 return active;
2470}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302471
2472static bool force_device_switch(struct audio_usecase *usecase)
2473{
2474 bool ret = false;
2475 bool is_it_true_mode = false;
2476
Zhou Song30f2c3e2018-02-08 14:02:15 +08002477 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302478 usecase->type == TRANSCODE_LOOPBACK_RX ||
2479 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002480 return false;
2481 }
2482
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002483 if(usecase->stream.out == NULL) {
2484 ALOGE("%s: stream.out is NULL", __func__);
2485 return false;
2486 }
2487
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302488 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002489 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002490 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2491 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302492 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2493 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2494 (!is_it_true_mode && adev->native_playback_enabled)){
2495 ret = true;
2496 ALOGD("napb: time to toggle native mode");
2497 }
2498 }
2499
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302500 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302501 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2502 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002503 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302504 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302505 ALOGD("Force a2dp device switch to update new encoder config");
2506 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002507 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302508
Florian Pfister1a84f312018-07-19 14:38:18 +02002509 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302510 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2511 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002512 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302513 return ret;
2514}
2515
Aalique Grahame22e49102018-12-18 14:23:57 -08002516static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2517{
2518 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2519}
2520
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302521bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2522{
2523 bool ret=false;
2524 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002525 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2526 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302527 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2528 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002529 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302530 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002531 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2532 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302533 ret = true;
2534
2535 return ret;
2536}
2537
2538bool is_a2dp_device(snd_device_t out_snd_device)
2539{
2540 bool ret=false;
2541 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2542 ret = true;
2543
2544 return ret;
2545}
2546
2547bool is_bt_soc_on(struct audio_device *adev)
2548{
2549 struct mixer_ctl *ctl;
2550 char *mixer_ctl_name = "BT SOC status";
2551 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2552 bool bt_soc_status = true;
2553 if (!ctl) {
2554 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2555 __func__, mixer_ctl_name);
2556 /*This is to ensure we dont break targets which dont have the kernel change*/
2557 return true;
2558 }
2559 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2560 ALOGD("BT SOC status: %d",bt_soc_status);
2561 return bt_soc_status;
2562}
2563
Zhou Song331c8e52019-08-26 14:16:12 +08002564static int configure_btsco_sample_rate(snd_device_t snd_device)
2565{
2566 struct mixer_ctl *ctl = NULL;
2567 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2568 char *rate_str = NULL;
2569 bool is_rx_dev = true;
2570
2571 if (is_btsco_device(snd_device, snd_device)) {
2572 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2573 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2574 if (!ctl_sr_tx || !ctl_sr_rx) {
2575 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2576 if (!ctl_sr)
2577 return -ENOSYS;
2578 }
2579
2580 switch (snd_device) {
2581 case SND_DEVICE_OUT_BT_SCO:
2582 rate_str = "KHZ_8";
2583 break;
2584 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2585 case SND_DEVICE_IN_BT_SCO_MIC:
2586 rate_str = "KHZ_8";
2587 is_rx_dev = false;
2588 break;
2589 case SND_DEVICE_OUT_BT_SCO_WB:
2590 rate_str = "KHZ_16";
2591 break;
2592 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2593 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2594 rate_str = "KHZ_16";
2595 is_rx_dev = false;
2596 break;
2597 default:
2598 return 0;
2599 }
2600
2601 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2602 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2603 return -ENOSYS;
2604 }
2605 return 0;
2606}
2607
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302608int out_standby_l(struct audio_stream *stream);
2609
Eric Laurent637e2d42018-11-15 12:24:31 -08002610struct stream_in *adev_get_active_input(const struct audio_device *adev)
2611{
2612 struct listnode *node;
2613 struct stream_in *last_active_in = NULL;
2614
2615 /* Get last added active input.
2616 * TODO: We may use a priority mechanism to pick highest priority active source */
2617 list_for_each(node, &adev->usecase_list)
2618 {
2619 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2620 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2621 last_active_in = usecase->stream.in;
2622 }
2623
2624 return last_active_in;
2625}
2626
2627struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2628{
2629 struct listnode *node;
2630
2631 /* First check active inputs with voice communication source and then
2632 * any input if audio mode is in communication */
2633 list_for_each(node, &adev->usecase_list)
2634 {
2635 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2636 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2637 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2638 return usecase->stream.in;
2639 }
2640 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2641 return adev_get_active_input(adev);
2642
2643 return NULL;
2644}
2645
Carter Hsu2e429db2019-05-14 18:50:52 +08002646/*
2647 * Aligned with policy.h
2648 */
2649static inline int source_priority(int inputSource)
2650{
2651 switch (inputSource) {
2652 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2653 return 9;
2654 case AUDIO_SOURCE_CAMCORDER:
2655 return 8;
2656 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2657 return 7;
2658 case AUDIO_SOURCE_UNPROCESSED:
2659 return 6;
2660 case AUDIO_SOURCE_MIC:
2661 return 5;
2662 case AUDIO_SOURCE_ECHO_REFERENCE:
2663 return 4;
2664 case AUDIO_SOURCE_FM_TUNER:
2665 return 3;
2666 case AUDIO_SOURCE_VOICE_RECOGNITION:
2667 return 2;
2668 case AUDIO_SOURCE_HOTWORD:
2669 return 1;
2670 default:
2671 break;
2672 }
2673 return 0;
2674}
2675
2676static struct stream_in *get_priority_input(struct audio_device *adev)
2677{
2678 struct listnode *node;
2679 struct audio_usecase *usecase;
2680 int last_priority = 0, priority;
2681 struct stream_in *priority_in = NULL;
2682 struct stream_in *in;
2683
2684 list_for_each(node, &adev->usecase_list) {
2685 usecase = node_to_item(node, struct audio_usecase, list);
2686 if (usecase->type == PCM_CAPTURE) {
2687 in = usecase->stream.in;
2688 if (!in)
2689 continue;
2690 priority = source_priority(in->source);
2691
2692 if (priority > last_priority) {
2693 last_priority = priority;
2694 priority_in = in;
2695 }
2696 }
2697 }
2698 return priority_in;
2699}
2700
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002701int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002703 snd_device_t out_snd_device = SND_DEVICE_NONE;
2704 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002705 struct audio_usecase *usecase = NULL;
2706 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002707 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002708 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302709 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002710 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302713 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2714
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 usecase = get_usecase_from_list(adev, uc_id);
2716 if (usecase == NULL) {
2717 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2718 return -EINVAL;
2719 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002721 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002722 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002723 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002724 (usecase->type == ICC_CALL) ||
2725 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302726 if(usecase->stream.out == NULL) {
2727 ALOGE("%s: stream.out is NULL", __func__);
2728 return -EINVAL;
2729 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002730 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002731 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2732 uc_id);
2733 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2734 uc_id);
2735 } else {
2736 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302737 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002738 in_snd_device = platform_get_input_snd_device(adev->platform,
2739 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302740 &usecase->stream.out->device_list,
2741 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002742 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002743 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302744 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302745 if (usecase->stream.inout == NULL) {
2746 ALOGE("%s: stream.inout is NULL", __func__);
2747 return -EINVAL;
2748 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002749 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302750 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2751 stream_out.format = usecase->stream.inout->out_config.format;
2752 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302753 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002754 assign_devices(&usecase->device_list,
2755 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302756 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2757 if (usecase->stream.inout == NULL) {
2758 ALOGE("%s: stream.inout is NULL", __func__);
2759 return -EINVAL;
2760 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302761 struct listnode out_devices;
2762 list_init(&out_devices);
2763 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2764 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002765 assign_devices(&usecase->device_list,
2766 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002767 } else {
2768 /*
2769 * If the voice call is active, use the sound devices of voice call usecase
2770 * so that it would not result any device switch. All the usecases will
2771 * be switched to new device when select_devices() is called for voice call
2772 * usecase. This is to avoid switching devices for voice call when
2773 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002774 * choose voice call device only if the use case device is
2775 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002776 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002777 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002778 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002779 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002780 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2781 is_codec_backend_out_device_type(&usecase->device_list)) ||
2782 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2783 is_codec_backend_in_device_type(&usecase->device_list)) ||
2784 is_single_device_type_equal(&vc_usecase->device_list,
2785 AUDIO_DEVICE_OUT_HEARING_AID) ||
2786 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002787 AUDIO_DEVICE_IN_VOICE_CALL) ||
2788 (is_single_device_type_equal(&usecase->device_list,
2789 AUDIO_DEVICE_IN_USB_HEADSET) &&
2790 is_single_device_type_equal(&vc_usecase->device_list,
2791 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002792 in_snd_device = vc_usecase->in_snd_device;
2793 out_snd_device = vc_usecase->out_snd_device;
2794 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002795 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002796 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002797 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002798 if ((voip_usecase != NULL) &&
2799 (usecase->type == PCM_PLAYBACK) &&
2800 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002801 out_snd_device_backend_match = platform_check_backends_match(
2802 voip_usecase->out_snd_device,
2803 platform_get_output_snd_device(
2804 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302805 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002806 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2808 (is_codec_backend_out_device_type(&usecase->device_list) ||
2809 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002810 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002811 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002812 in_snd_device = voip_usecase->in_snd_device;
2813 out_snd_device = voip_usecase->out_snd_device;
2814 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002815 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002816 hfp_ucid = audio_extn_hfp_get_usecase();
2817 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002818 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002819 in_snd_device = hfp_usecase->in_snd_device;
2820 out_snd_device = hfp_usecase->out_snd_device;
2821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002822 }
2823 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302824 if (usecase->stream.out == NULL) {
2825 ALOGE("%s: stream.out is NULL", __func__);
2826 return -EINVAL;
2827 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002828 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002830 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002831 struct stream_out *voip_out = adev->primary_output;
2832 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002833 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002834 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2835 else
2836 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302837 usecase->stream.out,
2838 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002839 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002840
Eric Laurent637e2d42018-11-15 12:24:31 -08002841 if (voip_usecase)
2842 voip_out = voip_usecase->stream.out;
2843
2844 if (usecase->stream.out == voip_out && voip_in != NULL)
2845 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002847 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302848 if (usecase->stream.in == NULL) {
2849 ALOGE("%s: stream.in is NULL", __func__);
2850 return -EINVAL;
2851 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002852 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002853 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002854 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002855 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002856 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002857 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002858
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002859 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002860 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002861 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2862 USECASE_AUDIO_PLAYBACK_VOIP);
2863
Carter Hsu2e429db2019-05-14 18:50:52 +08002864 usecase->stream.in->enable_ec_port = false;
2865
Zhou Song62ea0282020-03-22 19:53:01 +08002866 bool is_ha_usecase = adev->ha_proxy_enable ?
2867 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2868 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2869 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002870 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002871 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002872 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002873 } else if (adev->primary_output &&
2874 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002875 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002876 } else {
2877 /* forcing speaker o/p device to get matching i/p pair
2878 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002879 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002880 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002881 priority_in = voip_in;
2882 } else {
2883 /* get the input with the highest priority source*/
2884 priority_in = get_priority_input(adev);
2885
2886 if (!priority_in)
2887 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002888 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002889 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2890 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2891 }
2892 else
2893 in_snd_device = platform_get_input_snd_device(adev->platform,
2894 priority_in,
2895 &out_devices,
2896 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002897 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002898 }
2899 }
2900
2901 if (out_snd_device == usecase->out_snd_device &&
2902 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302903
2904 if (!force_device_switch(usecase))
2905 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 }
2907
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002908 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002909 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002910 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002911 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2912 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302913 }
2914
Aalique Grahame22e49102018-12-18 14:23:57 -08002915 if (out_snd_device != SND_DEVICE_NONE &&
2916 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2917 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2918 __func__,
2919 use_case_table[uc_id],
2920 adev->last_logged_snd_device[uc_id][0],
2921 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2922 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2923 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2924 -1,
2925 out_snd_device,
2926 platform_get_snd_device_name(out_snd_device),
2927 platform_get_snd_device_acdb_id(out_snd_device));
2928 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2929 }
2930 if (in_snd_device != SND_DEVICE_NONE &&
2931 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2932 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2933 __func__,
2934 use_case_table[uc_id],
2935 adev->last_logged_snd_device[uc_id][1],
2936 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2937 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2938 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2939 -1,
2940 in_snd_device,
2941 platform_get_snd_device_name(in_snd_device),
2942 platform_get_snd_device_acdb_id(in_snd_device));
2943 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2944 }
2945
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947 /*
2948 * Limitation: While in call, to do a device switch we need to disable
2949 * and enable both RX and TX devices though one of them is same as current
2950 * device.
2951 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002952 if ((usecase->type == VOICE_CALL) &&
2953 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2954 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002955 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002956 }
2957
2958 if (((usecase->type == VOICE_CALL) ||
2959 (usecase->type == VOIP_CALL)) &&
2960 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2961 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302962 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002963 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002964 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002965
2966 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302967 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002968 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002969 }
2970
Aalique Grahame22e49102018-12-18 14:23:57 -08002971 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2972 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002973 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302974 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002975 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2976 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2977 else
2978 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302979 }
2980
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002981 /* Disable current sound devices */
2982 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002983 disable_audio_route(adev, usecase);
2984 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 }
2986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002987 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002988 disable_audio_route(adev, usecase);
2989 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 }
2991
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002992 /* Applicable only on the targets that has external modem.
2993 * New device information should be sent to modem before enabling
2994 * the devices to reduce in-call device switch time.
2995 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002996 if ((usecase->type == VOICE_CALL) &&
2997 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2998 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002999 status = platform_switch_voice_call_enable_device_config(adev->platform,
3000 out_snd_device,
3001 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003002 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003003
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003004 /* Enable new sound devices */
3005 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003006 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303007 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303008 if (platform_check_codec_asrc_support(adev->platform))
3009 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003010 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003011 /* Enable haptics device for haptic usecase */
3012 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3013 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 }
3015
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003016 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303017 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003018 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003019 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003020
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303021 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003022 status = platform_switch_voice_call_device_post(adev->platform,
3023 out_snd_device,
3024 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003025
sangwoo170731f2013-06-08 15:36:36 +09003026 usecase->in_snd_device = in_snd_device;
3027 usecase->out_snd_device = out_snd_device;
3028
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303029 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3030 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303031 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003032 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003033 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003034 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3035 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3036 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3037 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3038 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3039 /*
3040 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3041 * configured device sample rate, if not update the COPP rate to be equal to the
3042 * device sample rate, else open COPP at stream sample rate
3043 */
3044 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3045 usecase->stream.out->sample_rate,
3046 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303047 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303048 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3049 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303050 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003051 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3052 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3053 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3054 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003055 }
3056 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003057
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003058 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003059
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003060 /* If input stream is already running then effect needs to be
3061 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003062 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003063 check_and_enable_effect(adev);
3064
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003065 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003066 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303067 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003068 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3069
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003070 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303071 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003072 voice_extn_compress_voip_is_started(adev))
3073 voice_set_sidetone(adev, out_snd_device, true);
3074 }
3075
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003076 /* Applicable only on the targets that has external modem.
3077 * Enable device command should be sent to modem only after
3078 * enabling voice call mixer controls
3079 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003080 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003081 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3082 out_snd_device,
3083 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303084
3085 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003086 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303087 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003088 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303089 if (is_bt_soc_on(adev) == false){
3090 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003091 if (in->pcm != NULL)
3092 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303093 }
3094 }
3095 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3096 && usecase->stream.out->started) {
3097 if (is_bt_soc_on(adev) == false) {
3098 ALOGD("BT SCO/A2DP disconnected while in connection");
3099 out_standby_l(&usecase->stream.out->stream.common);
3100 }
3101 }
3102 } else if ((usecase->stream.out != NULL) &&
3103 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303104 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3105 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003106 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303107 usecase->stream.out->started) {
3108 if (is_bt_soc_on(adev) == false) {
3109 ALOGD("BT SCO/A2dp disconnected while in connection");
3110 out_standby_l(&usecase->stream.out->stream.common);
3111 }
3112 }
3113 }
3114
Yung Ti Su70cb8242018-06-22 17:38:47 +08003115 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003116 struct stream_out *voip_out = voip_usecase->stream.out;
3117 audio_extn_utils_send_app_type_gain(adev,
3118 voip_out->app_type_cfg.app_type,
3119 &voip_out->app_type_cfg.gain[0]);
3120 }
3121
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003122 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 return status;
3125}
3126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127static int stop_input_stream(struct stream_in *in)
3128{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303129 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303131
3132 if (in == NULL) {
3133 ALOGE("%s: stream_in ptr is NULL", __func__);
3134 return -EINVAL;
3135 }
3136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003138 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139
Eric Laurent994a6932013-07-17 11:51:42 -07003140 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003141 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 uc_info = get_usecase_from_list(adev, in->usecase);
3143 if (uc_info == NULL) {
3144 ALOGE("%s: Could not find the usecase (%d) in the list",
3145 __func__, in->usecase);
3146 return -EINVAL;
3147 }
3148
Carter Hsu2e429db2019-05-14 18:50:52 +08003149 priority_in = get_priority_input(adev);
3150
Derek Chenea197282019-01-07 17:35:01 -08003151 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3152 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003153
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003154 /* Close in-call recording streams */
3155 voice_check_and_stop_incall_rec_usecase(adev, in);
3156
Eric Laurent150dbfe2013-02-27 14:31:02 -08003157 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003158 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003159
3160 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003161 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003163 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303164 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3165
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003166 list_remove(&uc_info->list);
3167 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168
Carter Hsu2e429db2019-05-14 18:50:52 +08003169 if (priority_in == in) {
3170 priority_in = get_priority_input(adev);
3171 if (priority_in)
3172 select_devices(adev, priority_in->usecase);
3173 }
3174
Vatsal Buchac09ae062018-11-14 13:25:08 +05303175 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003176 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 return ret;
3178}
3179
3180int start_input_stream(struct stream_in *in)
3181{
3182 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003183 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303185
3186 if (in == NULL) {
3187 ALOGE("%s: stream_in ptr is NULL", __func__);
3188 return -EINVAL;
3189 }
3190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003192 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003193 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194
Mingming Yin2664a5b2015-09-03 10:53:11 -07003195 if (get_usecase_from_list(adev, usecase) == NULL)
3196 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303197 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3198 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003199
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303200 if (CARD_STATUS_OFFLINE == in->card_status||
3201 CARD_STATUS_OFFLINE == adev->card_status) {
3202 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303203 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303204 goto error_config;
3205 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303206
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003207 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303208 if (!adev->bt_sco_on) {
3209 ALOGE("%s: SCO profile is not ready, return error", __func__);
3210 ret = -EIO;
3211 goto error_config;
3212 }
3213 }
3214
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003215 /* Check if source matches incall recording usecase criteria */
3216 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3217 if (ret)
3218 goto error_config;
3219 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003220 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3221
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303222 if (audio_extn_cin_attached_usecase(in))
3223 audio_extn_cin_acquire_usecase(in);
3224
Mingming Yin2664a5b2015-09-03 10:53:11 -07003225 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3226 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3227 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003228 ret = -EINVAL;
3229 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003230 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003231
Eric Laurentb23d5282013-05-14 15:27:20 -07003232 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 if (in->pcm_device_id < 0) {
3234 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3235 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003236 ret = -EINVAL;
3237 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003241
3242 if (!uc_info) {
3243 ret = -ENOMEM;
3244 goto error_config;
3245 }
3246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 uc_info->id = in->usecase;
3248 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003249 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003250 list_init(&uc_info->device_list);
3251 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003252 uc_info->in_snd_device = SND_DEVICE_NONE;
3253 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003255 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003256 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303257 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3258 adev->perf_lock_opts,
3259 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003260 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261
Derek Chenea197282019-01-07 17:35:01 -08003262 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3263 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003264
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303265 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3266
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303267 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303268 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303269 if (ret)
3270 goto error_open;
3271 else
3272 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003273 }
3274
Haynes Mathew George16081042017-05-31 17:16:49 -07003275 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003276 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003277 ALOGE("%s: pcm stream not ready", __func__);
3278 goto error_open;
3279 }
3280 ret = pcm_start(in->pcm);
3281 if (ret < 0) {
3282 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3283 goto error_open;
3284 }
3285 } else {
3286 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3287 unsigned int pcm_open_retry_count = 0;
3288
Zhou Song62ea0282020-03-22 19:53:01 +08003289 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3290 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003291 flags |= PCM_MMAP | PCM_NOIRQ;
3292 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3293 } else if (in->realtime) {
3294 flags |= PCM_MMAP | PCM_NOIRQ;
3295 }
3296
Garmond Leunge2433c32017-09-28 21:51:22 -07003297 if (audio_extn_ffv_get_stream() == in) {
3298 ALOGD("%s: ffv stream, update pcm config", __func__);
3299 audio_extn_ffv_update_pcm_config(&config);
3300 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003301 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3302 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3303
3304 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003305 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003306 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003307 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003308 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303309 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303310 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3311 adev->card_status = CARD_STATUS_OFFLINE;
3312 in->card_status = CARD_STATUS_OFFLINE;
3313 ret = -EIO;
3314 goto error_open;
3315 }
3316
Haynes Mathew George16081042017-05-31 17:16:49 -07003317 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3318 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3319 if (in->pcm != NULL) {
3320 pcm_close(in->pcm);
3321 in->pcm = NULL;
3322 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003323 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003324 ret = -EIO;
3325 goto error_open;
3326 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003327 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003328 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3329 continue;
3330 }
3331 break;
3332 }
3333
3334 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003335 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003336 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003337 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003338 if (ret < 0) {
3339 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3340 pcm_close(in->pcm);
3341 in->pcm = NULL;
3342 goto error_open;
3343 }
3344 register_in_stream(in);
3345 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003346 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003347 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003348 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003349 if (ret < 0) {
3350 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003351 pcm_close(in->pcm);
3352 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003353 goto error_open;
3354 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003355 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003356 }
3357
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003358 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003359 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3360 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003361
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003362 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303363 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3364
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303365done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003366 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303367 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303368 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303369 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003370 return ret;
3371
3372error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003373 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303374 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003376
Eric Laurentc8400632013-02-14 19:04:54 -08003377error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003378 if (audio_extn_cin_attached_usecase(in))
3379 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303380 /*
3381 * sleep 50ms to allow sufficient time for kernel
3382 * drivers to recover incases like SSR.
3383 */
3384 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003385 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303386 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003387 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388}
3389
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003390void lock_input_stream(struct stream_in *in)
3391{
3392 pthread_mutex_lock(&in->pre_lock);
3393 pthread_mutex_lock(&in->lock);
3394 pthread_mutex_unlock(&in->pre_lock);
3395}
3396
3397void lock_output_stream(struct stream_out *out)
3398{
3399 pthread_mutex_lock(&out->pre_lock);
3400 pthread_mutex_lock(&out->lock);
3401 pthread_mutex_unlock(&out->pre_lock);
3402}
3403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003404/* must be called with out->lock locked */
3405static int send_offload_cmd_l(struct stream_out* out, int command)
3406{
3407 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3408
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003409 if (!cmd) {
3410 ALOGE("failed to allocate mem for command 0x%x", command);
3411 return -ENOMEM;
3412 }
3413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 ALOGVV("%s %d", __func__, command);
3415
3416 cmd->cmd = command;
3417 list_add_tail(&out->offload_cmd_list, &cmd->node);
3418 pthread_cond_signal(&out->offload_cond);
3419 return 0;
3420}
3421
Gautam Manam14c198b2020-12-24 14:08:04 +05303422/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003423static void stop_compressed_output_l(struct stream_out *out)
3424{
Gautam Manam14c198b2020-12-24 14:08:04 +05303425 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303427 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003428 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003429 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 if (out->compr != NULL) {
3431 compress_stop(out->compr);
3432 while (out->offload_thread_blocked) {
3433 pthread_cond_wait(&out->cond, &out->lock);
3434 }
3435 }
3436}
3437
Varun Balaraje49253e2017-07-06 19:48:56 +05303438bool is_interactive_usecase(audio_usecase_t uc_id)
3439{
3440 unsigned int i;
3441 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3442 if (uc_id == interactive_usecases[i])
3443 return true;
3444 }
3445 return false;
3446}
3447
3448static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3449{
3450 audio_usecase_t ret_uc = USECASE_INVALID;
3451 unsigned int intract_uc_index;
3452 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3453
3454 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3455 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3456 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3457 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3458 ret_uc = interactive_usecases[intract_uc_index];
3459 break;
3460 }
3461 }
3462
3463 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3464 return ret_uc;
3465}
3466
3467static void free_interactive_usecase(struct audio_device *adev,
3468 audio_usecase_t uc_id)
3469{
3470 unsigned int interact_uc_index;
3471 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3472
3473 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3474 if (interactive_usecases[interact_uc_index] == uc_id) {
3475 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3476 break;
3477 }
3478 }
3479 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3480}
3481
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003482bool is_offload_usecase(audio_usecase_t uc_id)
3483{
3484 unsigned int i;
3485 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3486 if (uc_id == offload_usecases[i])
3487 return true;
3488 }
3489 return false;
3490}
3491
Dhananjay Kumarac341582017-02-23 23:42:25 +05303492static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003493{
vivek mehta446c3962015-09-14 10:57:35 -07003494 audio_usecase_t ret_uc = USECASE_INVALID;
3495 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003496 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003497 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303498 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003499 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3500 else
3501 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003502
vivek mehta446c3962015-09-14 10:57:35 -07003503 pthread_mutex_lock(&adev->lock);
3504 if (get_usecase_from_list(adev, ret_uc) != NULL)
3505 ret_uc = USECASE_INVALID;
3506 pthread_mutex_unlock(&adev->lock);
3507
3508 return ret_uc;
3509 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003510
3511 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003512 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3513 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3514 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3515 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003516 break;
3517 }
3518 }
vivek mehta446c3962015-09-14 10:57:35 -07003519
3520 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3521 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003522}
3523
3524static void free_offload_usecase(struct audio_device *adev,
3525 audio_usecase_t uc_id)
3526{
vivek mehta446c3962015-09-14 10:57:35 -07003527 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003528 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003529
3530 if (!adev->multi_offload_enable)
3531 return;
3532
3533 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3534 if (offload_usecases[offload_uc_index] == uc_id) {
3535 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003536 break;
3537 }
3538 }
3539 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3540}
3541
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542static void *offload_thread_loop(void *context)
3543{
3544 struct stream_out *out = (struct stream_out *) context;
3545 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003546 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003548 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003549 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3551
3552 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003553 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003554 out->offload_state = OFFLOAD_STATE_IDLE;
3555 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 for (;;) {
3557 struct offload_cmd *cmd = NULL;
3558 stream_callback_event_t event;
3559 bool send_callback = false;
3560
3561 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3562 __func__, list_empty(&out->offload_cmd_list),
3563 out->offload_state);
3564 if (list_empty(&out->offload_cmd_list)) {
3565 ALOGV("%s SLEEPING", __func__);
3566 pthread_cond_wait(&out->offload_cond, &out->lock);
3567 ALOGV("%s RUNNING", __func__);
3568 continue;
3569 }
3570
3571 item = list_head(&out->offload_cmd_list);
3572 cmd = node_to_item(item, struct offload_cmd, node);
3573 list_remove(item);
3574
3575 ALOGVV("%s STATE %d CMD %d out->compr %p",
3576 __func__, out->offload_state, cmd->cmd, out->compr);
3577
3578 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3579 free(cmd);
3580 break;
3581 }
3582
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003583 // allow OFFLOAD_CMD_ERROR reporting during standby
3584 // this is needed to handle failures during compress_open
3585 // Note however that on a pause timeout, the stream is closed
3586 // and no offload usecase will be active. Therefore this
3587 // special case is needed for compress_open failures alone
3588 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3589 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003590 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003591 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003592 pthread_cond_signal(&out->cond);
3593 continue;
3594 }
3595 out->offload_thread_blocked = true;
3596 pthread_mutex_unlock(&out->lock);
3597 send_callback = false;
3598 switch(cmd->cmd) {
3599 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003600 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003601 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003602 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603 send_callback = true;
3604 event = STREAM_CBK_EVENT_WRITE_READY;
3605 break;
3606 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003607 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303608 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003609 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303610 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003611 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303612 if (ret < 0)
3613 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303614 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303615 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003616 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003617 else
3618 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003619 if (-ENETRESET != ret && !(-EINTR == ret &&
3620 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303621 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303622 pthread_mutex_lock(&out->lock);
3623 out->send_new_metadata = 1;
3624 out->send_next_track_params = true;
3625 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303626 event = STREAM_CBK_EVENT_DRAIN_READY;
3627 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3628 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303629 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003630 break;
3631 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003632 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003633 ret = compress_drain(out->compr);
3634 ALOGD("copl(%p):out of compress_drain", out);
3635 // EINTR check avoids drain interruption due to SSR
3636 if (-ENETRESET != ret && !(-EINTR == ret &&
3637 CARD_STATUS_OFFLINE == out->card_status)) {
3638 send_callback = true;
3639 event = STREAM_CBK_EVENT_DRAIN_READY;
3640 } else
3641 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003642 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303643 case OFFLOAD_CMD_ERROR:
3644 ALOGD("copl(%p): sending error callback to AF", out);
3645 send_callback = true;
3646 event = STREAM_CBK_EVENT_ERROR;
3647 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648 default:
3649 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3650 break;
3651 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003652 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653 out->offload_thread_blocked = false;
3654 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003655 if (send_callback && out->client_callback) {
3656 ALOGVV("%s: sending client_callback event %d", __func__, event);
3657 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003658 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003659 free(cmd);
3660 }
3661
3662 pthread_cond_signal(&out->cond);
3663 while (!list_empty(&out->offload_cmd_list)) {
3664 item = list_head(&out->offload_cmd_list);
3665 list_remove(item);
3666 free(node_to_item(item, struct offload_cmd, node));
3667 }
3668 pthread_mutex_unlock(&out->lock);
3669
3670 return NULL;
3671}
3672
3673static int create_offload_callback_thread(struct stream_out *out)
3674{
3675 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3676 list_init(&out->offload_cmd_list);
3677 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3678 offload_thread_loop, out);
3679 return 0;
3680}
3681
3682static int destroy_offload_callback_thread(struct stream_out *out)
3683{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003684 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003685 stop_compressed_output_l(out);
3686 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3687
3688 pthread_mutex_unlock(&out->lock);
3689 pthread_join(out->offload_thread, (void **) NULL);
3690 pthread_cond_destroy(&out->offload_cond);
3691
3692 return 0;
3693}
3694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695static int stop_output_stream(struct stream_out *out)
3696{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303697 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 struct audio_usecase *uc_info;
3699 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003700 bool has_voip_usecase =
3701 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702
Eric Laurent994a6932013-07-17 11:51:42 -07003703 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003704 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 uc_info = get_usecase_from_list(adev, out->usecase);
3706 if (uc_info == NULL) {
3707 ALOGE("%s: Could not find the usecase (%d) in the list",
3708 __func__, out->usecase);
3709 return -EINVAL;
3710 }
3711
Zhou Songbaddf9f2020-11-20 13:57:39 +08003712 out->a2dp_muted = false;
3713
Derek Chenea197282019-01-07 17:35:01 -08003714 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3715 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003716
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003717 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303718 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003719 if (adev->visualizer_stop_output != NULL)
3720 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003721
3722 audio_extn_dts_remove_state_notifier_node(out->usecase);
3723
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003724 if (adev->offload_effects_stop_output != NULL)
3725 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003726 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3727 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3728 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003730
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003731 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3732 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003733 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003734 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003735
Eric Laurent150dbfe2013-02-27 14:31:02 -08003736 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003737 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003738
3739 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003740 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003741 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3742 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743
Aalique Grahame22e49102018-12-18 14:23:57 -08003744 audio_extn_extspk_update(adev->extspk);
3745
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003746 if (is_offload_usecase(out->usecase)) {
3747 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3748 adev->dsp_bit_width_enforce_mode,
3749 false);
3750 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003751 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003752 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3753 false);
3754
3755 if (ret != 0)
3756 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3757 /* default service interval was successfully updated,
3758 reopen USB backend with new service interval */
3759 ret = 0;
3760 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003761
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003762 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303763 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003764 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303765 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003766 ALOGV("Disable passthrough , reset mixer to pcm");
3767 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003768#ifdef AUDIO_GKI_ENABLED
3769 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3770 out->compr_config.codec->reserved[0] = 0;
3771#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003772 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003773#endif
Mingming Yin21854652016-04-13 11:54:02 -07003774 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003775 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3776 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003777
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303778 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003779 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303780 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303781
Manish Dewangan21a850a2017-08-14 12:03:55 +05303782 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003783 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3784 if (ret < 0)
3785 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3786 }
3787
Zhou Song642ec432020-12-23 16:11:10 +08003788 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003789 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003790 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003791 struct listnode *node;
3792 struct audio_usecase *usecase;
3793 list_for_each(node, &adev->usecase_list) {
3794 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003795 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3796 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303797 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003798 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003799 continue;
3800
3801 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3802 __func__, usecase->id, use_case_table[usecase->id],
3803 out->usecase, use_case_table[out->usecase]);
3804 select_devices(adev, usecase->id);
3805 }
3806 }
3807
Garmond Leung5fd0b552018-04-17 11:56:12 -07003808 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003809 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 return ret;
3811}
3812
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003813struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3814 unsigned int flags, unsigned int pcm_open_retry_count,
3815 struct pcm_config *config)
3816{
3817 struct pcm* pcm = NULL;
3818
3819 while (1) {
3820 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3821 if (pcm == NULL || !pcm_is_ready(pcm)) {
3822 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3823 if (pcm != NULL) {
3824 pcm_close(pcm);
3825 pcm = NULL;
3826 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003827 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003828 return NULL;
3829
Weiyin Jiang72197252019-10-09 11:49:32 +08003830 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003831 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3832 continue;
3833 }
3834 break;
3835 }
3836
3837 if (pcm_is_ready(pcm)) {
3838 int ret = pcm_prepare(pcm);
3839 if (ret < 0) {
3840 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3841 pcm_close(pcm);
3842 pcm = NULL;
3843 }
3844 }
3845
3846 return pcm;
3847}
3848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849int start_output_stream(struct stream_out *out)
3850{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 struct audio_usecase *uc_info;
3853 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003854 char mixer_ctl_name[128];
3855 struct mixer_ctl *ctl = NULL;
3856 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303857 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003858 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859
Haynes Mathew George380745d2017-10-04 15:27:45 -07003860 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003861 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3862 ret = -EINVAL;
3863 goto error_config;
3864 }
3865
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003866 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303867 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003868 get_device_types(&out->device_list), is_haptic_usecase);
3869
3870 bool is_speaker_active = compare_device_type(&out->device_list,
3871 AUDIO_DEVICE_OUT_SPEAKER);
3872 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3873 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303874
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303875 if (CARD_STATUS_OFFLINE == out->card_status ||
3876 CARD_STATUS_OFFLINE == adev->card_status) {
3877 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303878 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003879 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303880 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303881
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003882 //Update incall music usecase to reflect correct voice session
3883 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3884 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3885 if (ret != 0) {
3886 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3887 __func__, ret);
3888 goto error_config;
3889 }
3890 }
3891
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003892 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003893 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003894 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303895 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303896 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003897 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303898 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3899 ret = -EAGAIN;
3900 goto error_config;
3901 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303902 }
3903 }
3904 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003905 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303906 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003907 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303908 //combo usecase just by pass a2dp
3909 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003910 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303911 } else {
3912 ALOGE("%s: SCO profile is not ready, return error", __func__);
3913 ret = -EAGAIN;
3914 goto error_config;
3915 }
3916 }
3917 }
3918
Eric Laurentb23d5282013-05-14 15:27:20 -07003919 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920 if (out->pcm_device_id < 0) {
3921 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3922 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003923 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003924 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 }
3926
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003927 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003928 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3929 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003930 if (adev->haptic_pcm_device_id < 0) {
3931 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3932 __func__, adev->haptic_pcm_device_id, out->usecase);
3933 ret = -EINVAL;
3934 goto error_config;
3935 }
3936 }
3937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003939
3940 if (!uc_info) {
3941 ret = -ENOMEM;
3942 goto error_config;
3943 }
3944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945 uc_info->id = out->usecase;
3946 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003947 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003948 list_init(&uc_info->device_list);
3949 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003950 uc_info->in_snd_device = SND_DEVICE_NONE;
3951 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003952
3953 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003954 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003955 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3956 /* USB backend is not reopened immediately.
3957 This is eventually done as part of select_devices */
3958 }
3959
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003960 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961
Wei Wangf7ca6c92017-11-21 14:51:20 -08003962 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303963 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3964 adev->perf_lock_opts,
3965 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303966
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003967 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303968 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303969 if (audio_extn_passthru_is_enabled() &&
3970 audio_extn_passthru_is_passthrough_stream(out)) {
3971 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303972 }
3973 }
3974
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003975 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003976 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303977 if (!a2dp_combo) {
3978 check_a2dp_restore_l(adev, out, false);
3979 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003980 struct listnode dev;
3981 list_init(&dev);
3982 assign_devices(&dev, &out->device_list);
3983 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3984 reassign_device_list(&out->device_list,
3985 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003986 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003987 reassign_device_list(&out->device_list,
3988 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303989 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003990 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303991 }
3992 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303993 select_devices(adev, out->usecase);
3994 if (is_a2dp_out_device_type(&out->device_list) &&
3995 !adev->a2dp_started) {
3996 if (is_speaker_active || is_speaker_safe_active) {
3997 struct listnode dev;
3998 list_init(&dev);
3999 assign_devices(&dev, &out->device_list);
4000 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4001 reassign_device_list(&out->device_list,
4002 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4003 else
4004 reassign_device_list(&out->device_list,
4005 AUDIO_DEVICE_OUT_SPEAKER, "");
4006 select_devices(adev, out->usecase);
4007 assign_devices(&out->device_list, &dev);
4008 } else {
4009 ret = -EINVAL;
4010 goto error_open;
4011 }
4012 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304013 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004014
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004015 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4016 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004017 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004018 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004019
Derek Chenea197282019-01-07 17:35:01 -08004020 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4021 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004022
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004023 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4024 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004025
4026 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004027 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004028 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4029 ALOGE("%s: pcm stream not ready", __func__);
4030 goto error_open;
4031 }
4032 ret = pcm_start(out->pcm);
4033 if (ret < 0) {
4034 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4035 goto error_open;
4036 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004037 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004038 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004039 unsigned int flags = PCM_OUT;
4040 unsigned int pcm_open_retry_count = 0;
4041 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4042 flags |= PCM_MMAP | PCM_NOIRQ;
4043 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004044 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004045 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004046 } else
4047 flags |= PCM_MONOTONIC;
4048
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004049 if ((adev->vr_audio_mode_enabled) &&
4050 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4051 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4052 "PCM_Dev %d Topology", out->pcm_device_id);
4053 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4054 if (!ctl) {
4055 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4056 __func__, mixer_ctl_name);
4057 } else {
4058 //if success use ULLPP
4059 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4060 __func__, mixer_ctl_name, out->pcm_device_id);
4061 //There is a still a possibility that some sessions
4062 // that request for FAST|RAW when 3D audio is active
4063 //can go through ULLPP. Ideally we expects apps to
4064 //listen to audio focus and stop concurrent playback
4065 //Also, we will look for mode flag (voice_in_communication)
4066 //before enabling the realtime flag.
4067 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4068 }
4069 }
4070
Surendar Karka91fa3682018-07-02 18:12:12 +05304071 if (out->realtime)
4072 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4073 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4074
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004075 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4076 flags, pcm_open_retry_count,
4077 &(out->config));
4078 if (out->pcm == NULL) {
4079 ret = -EIO;
4080 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004081 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004082
4083 if (is_haptic_usecase) {
4084 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4085 adev->haptic_pcm_device_id,
4086 flags, pcm_open_retry_count,
4087 &(adev->haptics_config));
4088 // failure to open haptics pcm shouldnt stop audio,
4089 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004090
4091 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4092 ALOGD("%s: enable haptic audio synchronization", __func__);
4093 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4094 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004095 }
4096
Surendar Karka91fa3682018-07-02 18:12:12 +05304097 if (!out->realtime)
4098 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304099 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004100
Zhou Song2b8f28f2017-09-11 10:51:38 +08004101 // apply volume for voip playback after path is set up
4102 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4103 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304104 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4105 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304106 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4107 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004108 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4109 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304110 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004111 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004112 /*
4113 * set custom channel map if:
4114 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4115 * 2. custom channel map has been set by client
4116 * else default channel map of FC/FR/FL can always be set to DSP
4117 */
4118 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4119 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4120 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004121 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4122 adev->dsp_bit_width_enforce_mode,
4123 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004125 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004126 out->compr = compress_open(adev->snd_card,
4127 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004128 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004129 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304130 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304131 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4132 adev->card_status = CARD_STATUS_OFFLINE;
4133 out->card_status = CARD_STATUS_OFFLINE;
4134 ret = -EIO;
4135 goto error_open;
4136 }
4137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004138 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004139 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004140 compress_close(out->compr);
4141 out->compr = NULL;
4142 ret = -EIO;
4143 goto error_open;
4144 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304145 /* compress_open sends params of the track, so reset the flag here */
4146 out->is_compr_metadata_avail = false;
4147
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004148 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004150
Fred Oh3f43e742015-03-04 18:42:34 -08004151 /* Since small bufs uses blocking writes, a write will be blocked
4152 for the default max poll time (20s) in the event of an SSR.
4153 Reduce the poll time to observe and deal with SSR faster.
4154 */
Ashish Jain5106d362016-05-11 19:23:33 +05304155 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004156 compress_set_max_poll_wait(out->compr, 1000);
4157 }
4158
Manish Dewangan69426c82017-01-30 17:35:36 +05304159 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304160 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304161
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004162 audio_extn_dts_create_state_notifier_node(out->usecase);
4163 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4164 popcount(out->channel_mask),
4165 out->playback_started);
4166
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004167#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304168 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004169 audio_extn_dolby_send_ddp_endp_params(adev);
4170#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304171 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4172 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004173 if (adev->visualizer_start_output != NULL)
4174 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4175 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304176 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004177 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004178 }
Derek Chenf13dd492018-11-13 14:53:51 -08004179
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004180 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004181 /* Update cached volume from media to offload/direct stream */
4182 struct listnode *node = NULL;
4183 list_for_each(node, &adev->active_outputs_list) {
4184 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4185 streams_output_ctxt_t,
4186 list);
4187 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4188 out->volume_l = out_ctxt->output->volume_l;
4189 out->volume_r = out_ctxt->output->volume_r;
4190 }
4191 }
4192 out_set_compr_volume(&out->stream,
4193 out->volume_l, out->volume_r);
4194 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004196
4197 if (ret == 0) {
4198 register_out_stream(out);
4199 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004200 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4201 ALOGE("%s: pcm stream not ready", __func__);
4202 goto error_open;
4203 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004204 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004205 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004206 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004207 if (ret < 0)
4208 goto error_open;
4209 }
4210 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004211 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304212 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304213 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004214
vivek mehtad15d2bf2019-05-17 13:35:10 -07004215 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4216 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4217 audio_low_latency_hint_start();
4218 }
4219
Manish Dewangan21a850a2017-08-14 12:03:55 +05304220 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004221 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004222 if (ret < 0)
4223 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4224 }
4225
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004226 // consider a scenario where on pause lower layers are tear down.
4227 // so on resume, swap mixer control need to be sent only when
4228 // backend is active, hence rather than sending from enable device
4229 // sending it from start of streamtream
4230
4231 platform_set_swap_channels(adev, true);
4232
Haynes Mathew George380745d2017-10-04 15:27:45 -07004233 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304234 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004235 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004236error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004237 if (adev->haptic_pcm) {
4238 pcm_close(adev->haptic_pcm);
4239 adev->haptic_pcm = NULL;
4240 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004241 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304242 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004244error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304245 /*
4246 * sleep 50ms to allow sufficient time for kernel
4247 * drivers to recover incases like SSR.
4248 */
4249 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004250error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004251 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304252 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004253 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254}
4255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256static int check_input_parameters(uint32_t sample_rate,
4257 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004258 int channel_count,
4259 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004261 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304263 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4264 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4265 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004266 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004267 !audio_extn_compr_cap_format_supported(format) &&
4268 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004269 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004270
Aalique Grahame22e49102018-12-18 14:23:57 -08004271 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4272 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4273 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4274 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4275 return -EINVAL;
4276 }
4277
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004278 switch (channel_count) {
4279 case 1:
4280 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304281 case 3:
4282 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004283 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004284 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304285 case 10:
4286 case 12:
4287 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004288 break;
4289 default:
4290 ret = -EINVAL;
4291 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292
4293 switch (sample_rate) {
4294 case 8000:
4295 case 11025:
4296 case 12000:
4297 case 16000:
4298 case 22050:
4299 case 24000:
4300 case 32000:
4301 case 44100:
4302 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004303 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304304 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004305 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304306 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 break;
4308 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004309 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 }
4311
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004312 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313}
4314
Naresh Tanniru04f71882018-06-26 17:46:22 +05304315
4316/** Add a value in a list if not already present.
4317 * @return true if value was successfully inserted or already present,
4318 * false if the list is full and does not contain the value.
4319 */
4320static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4321 for (size_t i = 0; i < list_length; i++) {
4322 if (list[i] == value) return true; // value is already present
4323 if (list[i] == 0) { // no values in this slot
4324 list[i] = value;
4325 return true; // value inserted
4326 }
4327 }
4328 return false; // could not insert value
4329}
4330
4331/** Add channel_mask in supported_channel_masks if not already present.
4332 * @return true if channel_mask was successfully inserted or already present,
4333 * false if supported_channel_masks is full and does not contain channel_mask.
4334 */
4335static void register_channel_mask(audio_channel_mask_t channel_mask,
4336 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4337 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4338 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4339}
4340
4341/** Add format in supported_formats if not already present.
4342 * @return true if format was successfully inserted or already present,
4343 * false if supported_formats is full and does not contain format.
4344 */
4345static void register_format(audio_format_t format,
4346 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4347 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4348 "%s: stream can not declare supporting its format %x", __func__, format);
4349}
4350/** Add sample_rate in supported_sample_rates if not already present.
4351 * @return true if sample_rate was successfully inserted or already present,
4352 * false if supported_sample_rates is full and does not contain sample_rate.
4353 */
4354static void register_sample_rate(uint32_t sample_rate,
4355 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4356 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4357 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4358}
4359
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004360static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4361{
4362 uint32_t high = num1, low = num2, temp = 0;
4363
4364 if (!num1 || !num2)
4365 return 0;
4366
4367 if (num1 < num2) {
4368 high = num2;
4369 low = num1;
4370 }
4371
4372 while (low != 0) {
4373 temp = low;
4374 low = high % low;
4375 high = temp;
4376 }
4377 return (num1 * num2)/high;
4378}
4379
4380static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4381{
4382 uint32_t remainder = 0;
4383
4384 if (!multiplier)
4385 return num;
4386
4387 remainder = num % multiplier;
4388 if (remainder)
4389 num += (multiplier - remainder);
4390
4391 return num;
4392}
4393
Aalique Grahame22e49102018-12-18 14:23:57 -08004394static size_t get_stream_buffer_size(size_t duration_ms,
4395 uint32_t sample_rate,
4396 audio_format_t format,
4397 int channel_count,
4398 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399{
4400 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004401 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402
Aalique Grahame22e49102018-12-18 14:23:57 -08004403 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004404 if (is_low_latency)
4405 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304406
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004407 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004408 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409
Ralf Herzbd08d632018-09-28 15:50:49 +02004410 /* make sure the size is multiple of 32 bytes and additionally multiple of
4411 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004412 * At 48 kHz mono 16-bit PCM:
4413 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4414 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004415 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004416 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004417 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004418
4419 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420}
4421
Aalique Grahame22e49102018-12-18 14:23:57 -08004422static size_t get_input_buffer_size(uint32_t sample_rate,
4423 audio_format_t format,
4424 int channel_count,
4425 bool is_low_latency)
4426{
4427 /* Don't know if USB HIFI in this context so use true to be conservative */
4428 if (check_input_parameters(sample_rate, format, channel_count,
4429 true /*is_usb_hifi */) != 0)
4430 return 0;
4431
4432 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4433 sample_rate,
4434 format,
4435 channel_count,
4436 is_low_latency);
4437}
4438
Derek Chenf6318be2017-06-12 17:16:24 -04004439size_t get_output_period_size(uint32_t sample_rate,
4440 audio_format_t format,
4441 int channel_count,
4442 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304443{
4444 size_t size = 0;
4445 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4446
4447 if ((duration == 0) || (sample_rate == 0) ||
4448 (bytes_per_sample == 0) || (channel_count == 0)) {
4449 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4450 bytes_per_sample, channel_count);
4451 return -EINVAL;
4452 }
4453
4454 size = (sample_rate *
4455 duration *
4456 bytes_per_sample *
4457 channel_count) / 1000;
4458 /*
4459 * To have same PCM samples for all channels, the buffer size requires to
4460 * be multiple of (number of channels * bytes per sample)
4461 * For writes to succeed, the buffer must be written at address which is multiple of 32
4462 */
4463 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4464
4465 return (size/(channel_count * bytes_per_sample));
4466}
4467
Zhou Song48453a02018-01-10 17:50:59 +08004468static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304469{
4470 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004471 uint64_t written_frames = 0;
4472 uint64_t kernel_frames = 0;
4473 uint64_t dsp_frames = 0;
4474 uint64_t signed_frames = 0;
4475 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304476
4477 /* This adjustment accounts for buffering after app processor.
4478 * It is based on estimated DSP latency per use case, rather than exact.
4479 */
George Gao9ba8a142020-07-23 14:30:03 -07004480 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004481 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304482
Zhou Song48453a02018-01-10 17:50:59 +08004483 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004484 written_frames = out->written /
4485 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4486
Ashish Jain5106d362016-05-11 19:23:33 +05304487 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4488 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4489 * hence only estimate.
4490 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004491 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4492 kernel_frames = kernel_buffer_size /
4493 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304494
Weiyin Jiang4813da12020-05-28 00:37:28 +08004495 if (written_frames >= (kernel_frames + dsp_frames))
4496 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304497
Zhou Song48453a02018-01-10 17:50:59 +08004498 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304499 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004500 if (timestamp != NULL )
4501 *timestamp = out->writeAt;
4502 } else if (timestamp != NULL) {
4503 clock_gettime(CLOCK_MONOTONIC, timestamp);
4504 }
4505 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304506
Weiyin Jiang4813da12020-05-28 00:37:28 +08004507 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4508 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304509
4510 return actual_frames_rendered;
4511}
4512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4514{
4515 struct stream_out *out = (struct stream_out *)stream;
4516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004517 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518}
4519
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004520static int out_set_sample_rate(struct audio_stream *stream __unused,
4521 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522{
4523 return -ENOSYS;
4524}
4525
4526static size_t out_get_buffer_size(const struct audio_stream *stream)
4527{
4528 struct stream_out *out = (struct stream_out *)stream;
4529
Varun Balaraje49253e2017-07-06 19:48:56 +05304530 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304531 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304532 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304533 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4534 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4535 else
4536 return out->compr_config.fragment_size;
4537 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004538 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304539 else if (is_offload_usecase(out->usecase) &&
4540 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304541 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004542
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004543 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004544 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545}
4546
4547static uint32_t out_get_channels(const struct audio_stream *stream)
4548{
4549 struct stream_out *out = (struct stream_out *)stream;
4550
4551 return out->channel_mask;
4552}
4553
4554static audio_format_t out_get_format(const struct audio_stream *stream)
4555{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004556 struct stream_out *out = (struct stream_out *)stream;
4557
4558 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559}
4560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004561static int out_set_format(struct audio_stream *stream __unused,
4562 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563{
4564 return -ENOSYS;
4565}
4566
4567static int out_standby(struct audio_stream *stream)
4568{
4569 struct stream_out *out = (struct stream_out *)stream;
4570 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004571 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004572
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304573 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4574 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004576 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004578 if (adev->adm_deregister_stream)
4579 adev->adm_deregister_stream(adev->adm_data, out->handle);
4580
Weiyin Jiang280ea742020-09-08 20:28:22 +08004581 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004582 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004583 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004584
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004585 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004587 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4588 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304589 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004590 pthread_mutex_unlock(&adev->lock);
4591 pthread_mutex_unlock(&out->lock);
4592 ALOGD("VOIP output entered standby");
4593 return 0;
4594 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004595 if (out->pcm) {
4596 pcm_close(out->pcm);
4597 out->pcm = NULL;
4598 }
Meng Wanga09da002020-04-20 12:56:04 +08004599 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4600 if (adev->haptic_pcm) {
4601 pcm_close(adev->haptic_pcm);
4602 adev->haptic_pcm = NULL;
4603 }
4604
4605 if (adev->haptic_buffer != NULL) {
4606 free(adev->haptic_buffer);
4607 adev->haptic_buffer = NULL;
4608 adev->haptic_buffer_size = 0;
4609 }
4610 adev->haptic_pcm_device_id = 0;
4611 }
4612
Haynes Mathew George16081042017-05-31 17:16:49 -07004613 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4614 do_stop = out->playback_started;
4615 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004616
4617 if (out->mmap_shared_memory_fd >= 0) {
4618 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4619 __func__, out->mmap_shared_memory_fd);
4620 close(out->mmap_shared_memory_fd);
4621 out->mmap_shared_memory_fd = -1;
4622 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004623 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004624 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004625 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304626 out->send_next_track_params = false;
4627 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004628 out->gapless_mdata.encoder_delay = 0;
4629 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004630 if (out->compr != NULL) {
4631 compress_close(out->compr);
4632 out->compr = NULL;
4633 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004634 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004635 if (do_stop) {
4636 stop_output_stream(out);
4637 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304638 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004639 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004640 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 }
4642 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004643 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 return 0;
4645}
4646
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304647static int out_on_error(struct audio_stream *stream)
4648{
4649 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004650 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304651
4652 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004653 // always send CMD_ERROR for offload streams, this
4654 // is needed e.g. when SSR happens within compress_open
4655 // since the stream is active, offload_callback_thread is also active.
4656 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4657 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004658 }
4659 pthread_mutex_unlock(&out->lock);
4660
4661 status = out_standby(&out->stream.common);
4662
4663 lock_output_stream(out);
4664 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004665 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304666 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304667
4668 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4669 ALOGD("Setting previous card status if offline");
4670 out->prev_card_status_offline = true;
4671 }
4672
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304673 pthread_mutex_unlock(&out->lock);
4674
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004675 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304676}
4677
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304678/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004679 * standby implementation without locks, assumes that the callee already
4680 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304681 */
4682int out_standby_l(struct audio_stream *stream)
4683{
4684 struct stream_out *out = (struct stream_out *)stream;
4685 struct audio_device *adev = out->dev;
4686
4687 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4688 stream, out->usecase, use_case_table[out->usecase]);
4689
4690 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004691 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304692 if (adev->adm_deregister_stream)
4693 adev->adm_deregister_stream(adev->adm_data, out->handle);
4694
Weiyin Jiang280ea742020-09-08 20:28:22 +08004695 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304696 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004697 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304698
4699 out->standby = true;
4700 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4701 voice_extn_compress_voip_close_output_stream(stream);
4702 out->started = 0;
4703 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004704 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304705 return 0;
4706 } else if (!is_offload_usecase(out->usecase)) {
4707 if (out->pcm) {
4708 pcm_close(out->pcm);
4709 out->pcm = NULL;
4710 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004711 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4712 if (adev->haptic_pcm) {
4713 pcm_close(adev->haptic_pcm);
4714 adev->haptic_pcm = NULL;
4715 }
4716
4717 if (adev->haptic_buffer != NULL) {
4718 free(adev->haptic_buffer);
4719 adev->haptic_buffer = NULL;
4720 adev->haptic_buffer_size = 0;
4721 }
4722 adev->haptic_pcm_device_id = 0;
4723 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304724 } else {
4725 ALOGD("copl(%p):standby", out);
4726 out->send_next_track_params = false;
4727 out->is_compr_metadata_avail = false;
4728 out->gapless_mdata.encoder_delay = 0;
4729 out->gapless_mdata.encoder_padding = 0;
4730 if (out->compr != NULL) {
4731 compress_close(out->compr);
4732 out->compr = NULL;
4733 }
4734 }
4735 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004736 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304737 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004738 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304739 return 0;
4740}
4741
Aalique Grahame22e49102018-12-18 14:23:57 -08004742static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743{
Aalique Grahame22e49102018-12-18 14:23:57 -08004744 struct stream_out *out = (struct stream_out *)stream;
4745
4746 // We try to get the lock for consistency,
4747 // but it isn't necessary for these variables.
4748 // If we're not in standby, we may be blocked on a write.
4749 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4750 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4751 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4752
Andy Hunga1f48fa2019-07-01 18:14:53 -07004753 char buffer[256]; // for statistics formatting
4754 if (!is_offload_usecase(out->usecase)) {
4755 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4756 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4757 }
4758
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004759 if (out->start_latency_ms.n > 0) {
4760 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4761 dprintf(fd, " Start latency ms: %s\n", buffer);
4762 }
4763
Aalique Grahame22e49102018-12-18 14:23:57 -08004764 if (locked) {
4765 pthread_mutex_unlock(&out->lock);
4766 }
4767
4768 // dump error info
4769 (void)error_log_dump(
4770 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772 return 0;
4773}
4774
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004775static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4776{
4777 int ret = 0;
4778 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004779
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004780 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004781 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004782 return -EINVAL;
4783 }
4784
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304785 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004786
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004787 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4788 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304789 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004790 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004791 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4792 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304793 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004794 }
4795
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004796 ALOGV("%s new encoder delay %u and padding %u", __func__,
4797 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4798
4799 return 0;
4800}
4801
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004802static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4803{
4804 return out == adev->primary_output || out == adev->voice_tx_output;
4805}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004806
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304807// note: this call is safe only if the stream_cb is
4808// removed first in close_output_stream (as is done now).
4809static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4810{
4811 if (!stream || !parms)
4812 return;
4813
4814 struct stream_out *out = (struct stream_out *)stream;
4815 struct audio_device *adev = out->dev;
4816
4817 card_status_t status;
4818 int card;
4819 if (parse_snd_card_status(parms, &card, &status) < 0)
4820 return;
4821
4822 pthread_mutex_lock(&adev->lock);
4823 bool valid_cb = (card == adev->snd_card);
4824 pthread_mutex_unlock(&adev->lock);
4825
4826 if (!valid_cb)
4827 return;
4828
4829 lock_output_stream(out);
4830 if (out->card_status != status)
4831 out->card_status = status;
4832 pthread_mutex_unlock(&out->lock);
4833
4834 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4835 use_case_table[out->usecase],
4836 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4837
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304838 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304839 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304840 if (voice_is_call_state_active(adev) &&
4841 out == adev->primary_output) {
4842 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4843 pthread_mutex_lock(&adev->lock);
4844 voice_stop_call(adev);
4845 adev->mode = AUDIO_MODE_NORMAL;
4846 pthread_mutex_unlock(&adev->lock);
4847 }
4848 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304849 return;
4850}
4851
Kevin Rocardfce19002017-08-07 19:21:36 -07004852static int get_alive_usb_card(struct str_parms* parms) {
4853 int card;
4854 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4855 !audio_extn_usb_alive(card)) {
4856 return card;
4857 }
4858 return -ENODEV;
4859}
4860
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004861int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004862 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004863{
4864 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004865 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004867 bool bypass_a2dp = false;
4868 bool reconfig = false;
4869 unsigned long service_interval = 0;
4870
4871 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004872 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4873
4874 list_init(&new_devices);
4875 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004876
4877 lock_output_stream(out);
4878 pthread_mutex_lock(&adev->lock);
4879
4880 /*
4881 * When HDMI cable is unplugged the music playback is paused and
4882 * the policy manager sends routing=0. But the audioflinger continues
4883 * to write data until standby time (3sec). As the HDMI core is
4884 * turned off, the write gets blocked.
4885 * Avoid this by routing audio to speaker until standby.
4886 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004887 if (is_single_device_type_equal(&out->device_list,
4888 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004889 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004890 !audio_extn_passthru_is_passthrough_stream(out) &&
4891 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004892 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004893 }
4894 /*
4895 * When A2DP is disconnected the
4896 * music playback is paused and the policy manager sends routing=0
4897 * But the audioflinger continues to write data until standby time
4898 * (3sec). As BT is turned off, the write gets blocked.
4899 * Avoid this by routing audio to speaker until standby.
4900 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004901 if (is_a2dp_out_device_type(&out->device_list) &&
4902 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004903 !audio_extn_a2dp_source_is_ready() &&
4904 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004906 }
4907 /*
4908 * When USB headset is disconnected the music platback paused
4909 * and the policy manager send routing=0. But if the USB is connected
4910 * back before the standby time, AFE is not closed and opened
4911 * when USB is connected back. So routing to speker will guarantee
4912 * AFE reconfiguration and AFE will be opend once USB is connected again
4913 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004914 if (is_usb_out_device_type(&out->device_list) &&
4915 list_empty(&new_devices) &&
4916 !audio_extn_usb_connected(NULL)) {
4917 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4918 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004919 /* To avoid a2dp to sco overlapping / BT device improper state
4920 * check with BT lib about a2dp streaming support before routing
4921 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004922 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004923 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004924 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4925 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004926 //combo usecase just by pass a2dp
4927 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4928 bypass_a2dp = true;
4929 } else {
4930 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4931 /* update device to a2dp and don't route as BT returned error
4932 * However it is still possible a2dp routing called because
4933 * of current active device disconnection (like wired headset)
4934 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004935 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004936 pthread_mutex_unlock(&adev->lock);
4937 pthread_mutex_unlock(&out->lock);
4938 goto error;
4939 }
4940 }
4941 }
4942
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004943 // Workaround: If routing to an non existing usb device, fail gracefully
4944 // The routing request will otherwise block during 10 second
4945 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004946 if (is_usb_out_device_type(&new_devices)) {
4947 struct str_parms *parms =
4948 str_parms_create_str(get_usb_device_address(&new_devices));
4949 if (!parms)
4950 goto error;
4951 if ((card = get_alive_usb_card(parms)) >= 0) {
4952 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4953 pthread_mutex_unlock(&adev->lock);
4954 pthread_mutex_unlock(&out->lock);
4955 str_parms_destroy(parms);
4956 ret = -ENOSYS;
4957 goto error;
4958 }
4959 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004960 }
4961
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004962 // Workaround: If routing to an non existing hdmi device, fail gracefully
4963 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4964 (platform_get_edid_info_v2(adev->platform,
4965 out->extconn.cs.controller,
4966 out->extconn.cs.stream) != 0)) {
4967 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4968 pthread_mutex_unlock(&adev->lock);
4969 pthread_mutex_unlock(&out->lock);
4970 ret = -ENOSYS;
4971 goto error;
4972 }
4973
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004974 /*
4975 * select_devices() call below switches all the usecases on the same
4976 * backend to the new device. Refer to check_usecases_codec_backend() in
4977 * the select_devices(). But how do we undo this?
4978 *
4979 * For example, music playback is active on headset (deep-buffer usecase)
4980 * and if we go to ringtones and select a ringtone, low-latency usecase
4981 * will be started on headset+speaker. As we can't enable headset+speaker
4982 * and headset devices at the same time, select_devices() switches the music
4983 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4984 * So when the ringtone playback is completed, how do we undo the same?
4985 *
4986 * We are relying on the out_set_parameters() call on deep-buffer output,
4987 * once the ringtone playback is ended.
4988 * NOTE: We should not check if the current devices are same as new devices.
4989 * Because select_devices() must be called to switch back the music
4990 * playback to headset.
4991 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004992 if (!list_empty(&new_devices)) {
4993 bool same_dev = compare_devices(&out->device_list, &new_devices);
4994 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004995
4996 if (output_drives_call(adev, out)) {
4997 if (!voice_is_call_state_active(adev)) {
4998 if (adev->mode == AUDIO_MODE_IN_CALL) {
4999 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005000 ret = voice_start_call(adev);
5001 }
5002 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005003 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005004 adev->current_call_output = out;
5005 voice_update_devices_for_all_voice_usecases(adev);
5006 }
5007 }
5008
Mingshu Pang971ff702020-09-09 15:28:22 +08005009 if (is_usb_out_device_type(&out->device_list)) {
5010 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5011 audio_extn_usb_set_service_interval(true /*playback*/,
5012 service_interval,
5013 &reconfig);
5014 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5015 }
5016
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005017 if (!out->standby) {
5018 if (!same_dev) {
5019 ALOGV("update routing change");
5020 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5021 adev->perf_lock_opts,
5022 adev->perf_lock_opts_size);
5023 if (adev->adm_on_routing_change)
5024 adev->adm_on_routing_change(adev->adm_data,
5025 out->handle);
5026 }
5027 if (!bypass_a2dp) {
5028 select_devices(adev, out->usecase);
5029 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005030 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5031 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005032 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005033 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005034 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005035 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005036 }
5037
5038 if (!same_dev) {
5039 // on device switch force swap, lower functions will make sure
5040 // to check if swap is allowed or not.
5041 platform_set_swap_channels(adev, true);
5042 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5043 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005044 pthread_mutex_lock(&out->latch_lock);
5045 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5046 if (out->a2dp_muted) {
5047 out->a2dp_muted = false;
5048 if (is_offload_usecase(out->usecase))
5049 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5050 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5051 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005052 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005053 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005054 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5055 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5056 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005057 }
5058 }
5059
5060 pthread_mutex_unlock(&adev->lock);
5061 pthread_mutex_unlock(&out->lock);
5062
5063 /*handles device and call state changes*/
5064 audio_extn_extspk_update(adev->extspk);
5065
5066error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005067 ALOGV("%s: exit: code(%d)", __func__, ret);
5068 return ret;
5069}
5070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005071static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5072{
5073 struct stream_out *out = (struct stream_out *)stream;
5074 struct audio_device *adev = out->dev;
5075 struct str_parms *parms;
5076 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005077 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005078 int ext_controller = -1;
5079 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005080
sangwoobc677242013-08-08 16:53:43 +09005081 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005082 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005083 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305084 if (!parms)
5085 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005086
5087 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5088 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005089 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005090 out->extconn.cs.controller = ext_controller;
5091 out->extconn.cs.stream = ext_stream;
5092 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5093 use_case_table[out->usecase], out->extconn.cs.controller,
5094 out->extconn.cs.stream);
5095 }
5096
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005097 if (out == adev->primary_output) {
5098 pthread_mutex_lock(&adev->lock);
5099 audio_extn_set_parameters(adev, parms);
5100 pthread_mutex_unlock(&adev->lock);
5101 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005102 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005103 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005104 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005105
5106 audio_extn_dts_create_state_notifier_node(out->usecase);
5107 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5108 popcount(out->channel_mask),
5109 out->playback_started);
5110
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005111 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005112 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005113
Surendar Karkaf51b5842018-04-26 11:28:38 +05305114 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5115 sizeof(value));
5116 if (err >= 0) {
5117 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5118 audio_extn_send_dual_mono_mixing_coefficients(out);
5119 }
5120
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305121 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5122 if (err >= 0) {
5123 strlcpy(out->profile, value, sizeof(out->profile));
5124 ALOGV("updating stream profile with value '%s'", out->profile);
5125 lock_output_stream(out);
5126 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5127 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005128 &out->device_list, out->flags,
5129 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305130 out->sample_rate, out->bit_width,
5131 out->channel_mask, out->profile,
5132 &out->app_type_cfg);
5133 pthread_mutex_unlock(&out->lock);
5134 }
5135
Alexy Joseph98988832017-01-13 14:56:59 -08005136 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005137 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5138 // and vendor.audio.hal.output.suspend.supported is set to true
5139 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005140 //check suspend parameter only for low latency and if the property
5141 //is enabled
5142 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5143 ALOGI("%s: got suspend_playback %s", __func__, value);
5144 lock_output_stream(out);
5145 if (!strncmp(value, "false", 5)) {
5146 //suspend_playback=false is supposed to set QOS value back to 75%
5147 //the mixer control sent with value Enable will achieve that
5148 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5149 } else if (!strncmp (value, "true", 4)) {
5150 //suspend_playback=true is supposed to remove QOS value
5151 //resetting the mixer control will set the default value
5152 //for the mixer control which is Disable and this removes the QOS vote
5153 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5154 } else {
5155 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5156 " got %s", __func__, value);
5157 ret = -1;
5158 }
5159
5160 if (ret != 0) {
5161 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5162 __func__, out->pm_qos_mixer_path, ret);
5163 }
5164
5165 pthread_mutex_unlock(&out->lock);
5166 }
5167 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005168
Alexy Joseph98988832017-01-13 14:56:59 -08005169 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005170 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305171error:
Eric Laurent994a6932013-07-17 11:51:42 -07005172 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005173 return ret;
5174}
5175
Paul McLeana50b7332018-12-17 08:24:21 -07005176static int in_set_microphone_direction(const struct audio_stream_in *stream,
5177 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005178 struct stream_in *in = (struct stream_in *)stream;
5179
5180 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5181
5182 in->direction = dir;
5183
5184 if (in->standby)
5185 return 0;
5186
5187 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005188}
5189
5190static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005191 struct stream_in *in = (struct stream_in *)stream;
5192
5193 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5194
5195 if (zoom > 1.0 || zoom < -1.0)
5196 return -EINVAL;
5197
5198 in->zoom = zoom;
5199
5200 if (in->standby)
5201 return 0;
5202
5203 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005204}
5205
5206
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005207static bool stream_get_parameter_channels(struct str_parms *query,
5208 struct str_parms *reply,
5209 audio_channel_mask_t *supported_channel_masks) {
5210 int ret = -1;
5211 char value[512];
5212 bool first = true;
5213 size_t i, j;
5214
5215 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5216 ret = 0;
5217 value[0] = '\0';
5218 i = 0;
5219 while (supported_channel_masks[i] != 0) {
5220 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5221 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5222 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305223 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005224
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305225 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005226 first = false;
5227 break;
5228 }
5229 }
5230 i++;
5231 }
5232 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5233 }
5234 return ret == 0;
5235}
5236
5237static bool stream_get_parameter_formats(struct str_parms *query,
5238 struct str_parms *reply,
5239 audio_format_t *supported_formats) {
5240 int ret = -1;
5241 char value[256];
5242 size_t i, j;
5243 bool first = true;
5244
5245 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5246 ret = 0;
5247 value[0] = '\0';
5248 i = 0;
5249 while (supported_formats[i] != 0) {
5250 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5251 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5252 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305253 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005254 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305255 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005256 first = false;
5257 break;
5258 }
5259 }
5260 i++;
5261 }
5262 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5263 }
5264 return ret == 0;
5265}
5266
5267static bool stream_get_parameter_rates(struct str_parms *query,
5268 struct str_parms *reply,
5269 uint32_t *supported_sample_rates) {
5270
5271 int i;
5272 char value[256];
5273 int ret = -1;
5274 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5275 ret = 0;
5276 value[0] = '\0';
5277 i=0;
5278 int cursor = 0;
5279 while (supported_sample_rates[i]) {
5280 int avail = sizeof(value) - cursor;
5281 ret = snprintf(value + cursor, avail, "%s%d",
5282 cursor > 0 ? "|" : "",
5283 supported_sample_rates[i]);
5284 if (ret < 0 || ret >= avail) {
5285 // if cursor is at the last element of the array
5286 // overwrite with \0 is duplicate work as
5287 // snprintf already put a \0 in place.
5288 // else
5289 // we had space to write the '|' at value[cursor]
5290 // (which will be overwritten) or no space to fill
5291 // the first element (=> cursor == 0)
5292 value[cursor] = '\0';
5293 break;
5294 }
5295 cursor += ret;
5296 ++i;
5297 }
5298 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5299 value);
5300 }
5301 return ret >= 0;
5302}
5303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5305{
5306 struct stream_out *out = (struct stream_out *)stream;
5307 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005308 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005309 char value[256];
5310 struct str_parms *reply = str_parms_create();
5311 size_t i, j;
5312 int ret;
5313 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005314
5315 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005316 if (reply) {
5317 str_parms_destroy(reply);
5318 }
5319 if (query) {
5320 str_parms_destroy(query);
5321 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005322 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5323 return NULL;
5324 }
5325
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005326 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005327 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5328 if (ret >= 0) {
5329 value[0] = '\0';
5330 i = 0;
5331 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005332 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5333 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005335 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005336 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005337 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 first = false;
5339 break;
5340 }
5341 }
5342 i++;
5343 }
5344 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5345 str = str_parms_to_str(reply);
5346 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005347 voice_extn_out_get_parameters(out, query, reply);
5348 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005350
Alexy Joseph62142aa2015-11-16 15:10:34 -08005351
5352 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5353 if (ret >= 0) {
5354 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305355 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5356 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005357 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305358 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005359 } else {
5360 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305361 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005362 }
5363 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005364 if (str)
5365 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005366 str = str_parms_to_str(reply);
5367 }
5368
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005369 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5370 if (ret >= 0) {
5371 value[0] = '\0';
5372 i = 0;
5373 first = true;
5374 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005375 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5376 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005377 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005378 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005379 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005380 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005381 first = false;
5382 break;
5383 }
5384 }
5385 i++;
5386 }
5387 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005388 if (str)
5389 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005390 str = str_parms_to_str(reply);
5391 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005392
5393 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5394 if (ret >= 0) {
5395 value[0] = '\0';
5396 i = 0;
5397 first = true;
5398 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005399 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5400 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005401 if (!first) {
5402 strlcat(value, "|", sizeof(value));
5403 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005404 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005405 first = false;
5406 break;
5407 }
5408 }
5409 i++;
5410 }
5411 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5412 if (str)
5413 free(str);
5414 str = str_parms_to_str(reply);
5415 }
5416
Alexy Joseph98988832017-01-13 14:56:59 -08005417 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5418 //only low latency track supports suspend_resume
5419 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005420 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005421 if (str)
5422 free(str);
5423 str = str_parms_to_str(reply);
5424 }
5425
5426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005427 str_parms_destroy(query);
5428 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005429 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430 return str;
5431}
5432
5433static uint32_t out_get_latency(const struct audio_stream_out *stream)
5434{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005435 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005436 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005437 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005438
Alexy Josephaa54c872014-12-03 02:46:47 -08005439 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305440 lock_output_stream(out);
5441 latency = audio_extn_utils_compress_get_dsp_latency(out);
5442 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005443 } else if ((out->realtime) ||
5444 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005445 // since the buffer won't be filled up faster than realtime,
5446 // return a smaller number
5447 if (out->config.rate)
5448 period_ms = (out->af_period_multiplier * out->config.period_size *
5449 1000) / (out->config.rate);
5450 else
5451 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005452 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005453 } else {
5454 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005455 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005456 }
5457
Zhou Songd2537a02020-06-11 22:04:46 +08005458 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005459 latency += audio_extn_a2dp_get_encoder_latency();
5460
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305461 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005462 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463}
5464
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305465static float AmpToDb(float amplification)
5466{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305467 float db = DSD_VOLUME_MIN_DB;
5468 if (amplification > 0) {
5469 db = 20 * log10(amplification);
5470 if(db < DSD_VOLUME_MIN_DB)
5471 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305472 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305473 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305474}
5475
Arun Mirpuri5d170872019-03-26 13:21:31 -07005476static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5477 float right)
5478{
5479 struct stream_out *out = (struct stream_out *)stream;
5480 long volume = 0;
5481 char mixer_ctl_name[128] = "";
5482 struct audio_device *adev = out->dev;
5483 struct mixer_ctl *ctl = NULL;
5484 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5485 PCM_PLAYBACK);
5486
5487 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5488 "Playback %d Volume", pcm_device_id);
5489 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5490 if (!ctl) {
5491 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5492 __func__, mixer_ctl_name);
5493 return -EINVAL;
5494 }
5495 if (left != right)
5496 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5497 __func__, left, right);
5498 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5499 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5500 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5501 __func__, mixer_ctl_name, volume);
5502 return -EINVAL;
5503 }
5504 return 0;
5505}
5506
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305507static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5508 float right)
5509{
5510 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305511 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305512 char mixer_ctl_name[128];
5513 struct audio_device *adev = out->dev;
5514 struct mixer_ctl *ctl;
5515 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5516 PCM_PLAYBACK);
5517
5518 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5519 "Compress Playback %d Volume", pcm_device_id);
5520 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5521 if (!ctl) {
5522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5523 __func__, mixer_ctl_name);
5524 return -EINVAL;
5525 }
5526 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5527 __func__, mixer_ctl_name, left, right);
5528 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5529 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5530 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5531
5532 return 0;
5533}
5534
Zhou Song2b8f28f2017-09-11 10:51:38 +08005535static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5536 float right)
5537{
5538 struct stream_out *out = (struct stream_out *)stream;
5539 char mixer_ctl_name[] = "App Type Gain";
5540 struct audio_device *adev = out->dev;
5541 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305542 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005543
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005544 if (!is_valid_volume(left, right)) {
5545 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5546 __func__, left, right);
5547 return -EINVAL;
5548 }
5549
Zhou Song2b8f28f2017-09-11 10:51:38 +08005550 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5551 if (!ctl) {
5552 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5553 __func__, mixer_ctl_name);
5554 return -EINVAL;
5555 }
5556
5557 set_values[0] = 0; //0: Rx Session 1:Tx Session
5558 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305559 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5560 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005561
5562 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5563 return 0;
5564}
5565
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305566static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5567 float right)
5568{
5569 struct stream_out *out = (struct stream_out *)stream;
5570 /* Volume control for pcm playback */
5571 if (left != right) {
5572 return -EINVAL;
5573 } else {
5574 char mixer_ctl_name[128];
5575 struct audio_device *adev = out->dev;
5576 struct mixer_ctl *ctl;
5577 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5578 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5579 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5580 if (!ctl) {
5581 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5582 return -EINVAL;
5583 }
5584
5585 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5586 int ret = mixer_ctl_set_value(ctl, 0, volume);
5587 if (ret < 0) {
5588 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5589 return -EINVAL;
5590 }
5591
5592 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5593
5594 return 0;
5595 }
5596}
5597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598static int out_set_volume(struct audio_stream_out *stream, float left,
5599 float right)
5600{
Eric Laurenta9024de2013-04-04 09:19:12 -07005601 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005602 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305603 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005604
Arun Mirpuri5d170872019-03-26 13:21:31 -07005605 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005606 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5607 /* only take left channel into account: the API is for stereo anyway */
5608 out->muted = (left == 0.0f);
5609 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005610 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305611 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005612 /*
5613 * Set mute or umute on HDMI passthrough stream.
5614 * Only take left channel into account.
5615 * Mute is 0 and unmute 1
5616 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305617 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305618 } else if (out->format == AUDIO_FORMAT_DSD){
5619 char mixer_ctl_name[128] = "DSD Volume";
5620 struct audio_device *adev = out->dev;
5621 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5622
5623 if (!ctl) {
5624 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5625 __func__, mixer_ctl_name);
5626 return -EINVAL;
5627 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305628 volume[0] = (long)(AmpToDb(left));
5629 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305630 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5631 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005632 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005633 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005634 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5635 struct listnode *node = NULL;
5636 list_for_each(node, &adev->active_outputs_list) {
5637 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5638 streams_output_ctxt_t,
5639 list);
5640 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5641 out->volume_l = out_ctxt->output->volume_l;
5642 out->volume_r = out_ctxt->output->volume_r;
5643 }
5644 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005645 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005646 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005647 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5648 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005649 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005650 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005651 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005652 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005653 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5654 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305655 ret = out_set_compr_volume(stream, left, right);
5656 out->volume_l = left;
5657 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005658 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305659 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005660 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005661 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005662 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5663 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005664 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005665 if (!out->standby) {
5666 audio_extn_utils_send_app_type_gain(out->dev,
5667 out->app_type_cfg.app_type,
5668 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005669 if (!out->a2dp_muted)
5670 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005671 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005672 out->volume_l = left;
5673 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005674 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005675 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005676 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5677 ALOGV("%s: MMAP set volume called", __func__);
5678 if (!out->standby)
5679 ret = out_set_mmap_volume(stream, left, right);
5680 out->volume_l = left;
5681 out->volume_r = right;
5682 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305683 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305684 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5685 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005686 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305687 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005688 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305689 ret = out_set_pcm_volume(stream, left, right);
5690 else
5691 out->apply_volume = true;
5692
5693 out->volume_l = left;
5694 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005695 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305696 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005697 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5698 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005699 pthread_mutex_lock(&out->latch_lock);
5700 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005701 ret = out_set_pcm_volume(stream, left, right);
5702 out->volume_l = left;
5703 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005704 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005705 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005706 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 return -ENOSYS;
5709}
5710
Zhou Songc9672822017-08-16 16:01:39 +08005711static void update_frames_written(struct stream_out *out, size_t bytes)
5712{
5713 size_t bpf = 0;
5714
5715 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5716 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5717 bpf = 1;
5718 else if (!is_offload_usecase(out->usecase))
5719 bpf = audio_bytes_per_sample(out->format) *
5720 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005721
5722 pthread_mutex_lock(&out->position_query_lock);
5723 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005724 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005725 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5726 }
5727 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005728}
5729
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005730int split_and_write_audio_haptic_data(struct stream_out *out,
5731 const void *buffer, size_t bytes_to_write)
5732{
5733 struct audio_device *adev = out->dev;
5734
5735 int ret = 0;
5736 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5737 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5738 size_t frame_size = channel_count * bytes_per_sample;
5739 size_t frame_count = bytes_to_write / frame_size;
5740
5741 bool force_haptic_path =
5742 property_get_bool("vendor.audio.test_haptic", false);
5743
5744 // extract Haptics data from Audio buffer
5745 bool alloc_haptic_buffer = false;
5746 int haptic_channel_count = adev->haptics_config.channels;
5747 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5748 size_t audio_frame_size = frame_size - haptic_frame_size;
5749 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5750
5751 if (adev->haptic_buffer == NULL) {
5752 alloc_haptic_buffer = true;
5753 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5754 free(adev->haptic_buffer);
5755 adev->haptic_buffer_size = 0;
5756 alloc_haptic_buffer = true;
5757 }
5758
5759 if (alloc_haptic_buffer) {
5760 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005761 if(adev->haptic_buffer == NULL) {
5762 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5763 return -ENOMEM;
5764 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005765 adev->haptic_buffer_size = total_haptic_buffer_size;
5766 }
5767
5768 size_t src_index = 0, aud_index = 0, hap_index = 0;
5769 uint8_t *audio_buffer = (uint8_t *)buffer;
5770 uint8_t *haptic_buffer = adev->haptic_buffer;
5771
5772 // This is required for testing only. This works for stereo data only.
5773 // One channel is fed to audio stream and other to haptic stream for testing.
5774 if (force_haptic_path)
5775 audio_frame_size = haptic_frame_size = bytes_per_sample;
5776
5777 for (size_t i = 0; i < frame_count; i++) {
5778 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5779 audio_frame_size);
5780 aud_index += audio_frame_size;
5781 src_index += audio_frame_size;
5782
5783 if (adev->haptic_pcm)
5784 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5785 haptic_frame_size);
5786 hap_index += haptic_frame_size;
5787 src_index += haptic_frame_size;
5788
5789 // This is required for testing only.
5790 // Discard haptic channel data.
5791 if (force_haptic_path)
5792 src_index += haptic_frame_size;
5793 }
5794
5795 // write to audio pipeline
5796 ret = pcm_write(out->pcm, (void *)audio_buffer,
5797 frame_count * audio_frame_size);
5798
5799 // write to haptics pipeline
5800 if (adev->haptic_pcm)
5801 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5802 frame_count * haptic_frame_size);
5803
5804 return ret;
5805}
5806
Aalique Grahame22e49102018-12-18 14:23:57 -08005807#ifdef NO_AUDIO_OUT
5808static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5809 const void *buffer __unused, size_t bytes)
5810{
5811 struct stream_out *out = (struct stream_out *)stream;
5812
5813 /* No Output device supported other than BT for playback.
5814 * Sleep for the amount of buffer duration
5815 */
5816 lock_output_stream(out);
5817 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5818 (const struct audio_stream_out *)&out->stream) /
5819 out_get_sample_rate(&out->stream.common));
5820 pthread_mutex_unlock(&out->lock);
5821 return bytes;
5822}
5823#endif
5824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5826 size_t bytes)
5827{
5828 struct stream_out *out = (struct stream_out *)stream;
5829 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005830 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305831 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005832 const size_t frame_size = audio_stream_out_frame_size(stream);
5833 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305834 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005835 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005836
Haynes Mathew George380745d2017-10-04 15:27:45 -07005837 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005838 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305839
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305840 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005841
Dhananjay Kumarac341582017-02-23 23:42:25 +05305842 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305843 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305844 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5845 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005846 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305847 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305848 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305849 ALOGD(" %s: sound card is not active/SSR state", __func__);
5850 ret= -EIO;
5851 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305852 }
5853 }
5854
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305855 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305856 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305857 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305858 goto exit;
5859 }
5860
Haynes Mathew George16081042017-05-31 17:16:49 -07005861 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5862 ret = -EINVAL;
5863 goto exit;
5864 }
5865
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005866 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305867 !out->is_iec61937_info_available) {
5868
5869 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5870 out->is_iec61937_info_available = true;
5871 } else if (audio_extn_passthru_is_enabled()) {
5872 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305873 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305874
5875 if((out->format == AUDIO_FORMAT_DTS) ||
5876 (out->format == AUDIO_FORMAT_DTS_HD)) {
5877 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5878 buffer, bytes);
5879 if (ret) {
5880 if (ret != -ENOSYS) {
5881 out->is_iec61937_info_available = false;
5882 ALOGD("iec61937 transmission info not yet updated retry");
5883 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305884 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305885 /* if stream has started and after that there is
5886 * stream config change (iec transmission config)
5887 * then trigger select_device to update backend configuration.
5888 */
5889 out->stream_config_changed = true;
5890 pthread_mutex_lock(&adev->lock);
5891 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305892 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005893 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305894 ret = -EINVAL;
5895 goto exit;
5896 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305897 pthread_mutex_unlock(&adev->lock);
5898 out->stream_config_changed = false;
5899 out->is_iec61937_info_available = true;
5900 }
5901 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305902
Meng Wang4c32fb42020-01-16 17:57:11 +08005903#ifdef AUDIO_GKI_ENABLED
5904 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5905 compr_passthr = out->compr_config.codec->reserved[0];
5906#else
5907 compr_passthr = out->compr_config.codec->compr_passthr;
5908#endif
5909
Garmond Leung317cbf12017-09-13 16:20:50 -07005910 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005911 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305912 (out->is_iec61937_info_available == true)) {
5913 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5914 ret = -EINVAL;
5915 goto exit;
5916 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305917 }
5918 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305919
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005920 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005921 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005922 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5923 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005924 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305925 ret = -EIO;
5926 goto exit;
5927 }
5928 }
5929 }
5930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005931 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005932 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005933 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5934
Eric Laurent150dbfe2013-02-27 14:31:02 -08005935 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005936 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5937 ret = voice_extn_compress_voip_start_output_stream(out);
5938 else
5939 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005940 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005941 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005942 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005943 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005944 goto exit;
5945 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305946 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005947 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005948
5949 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005950 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005951 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305952 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005953 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005954 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305955
5956 if ((out->is_iec61937_info_available == true) &&
5957 (audio_extn_passthru_is_passthrough_stream(out))&&
5958 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5959 ret = -EINVAL;
5960 goto exit;
5961 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305962 if (out->set_dual_mono)
5963 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005964
5965 // log startup time in ms.
5966 simple_stats_log(
5967 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005968 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005969
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005970 if (adev->is_channel_status_set == false &&
5971 compare_device_type(&out->device_list,
5972 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005973 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305974 adev->is_channel_status_set = true;
5975 }
5976
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305977 if ((adev->use_old_pspd_mix_ctrl == true) &&
5978 (out->pspd_coeff_sent == false)) {
5979 /*
5980 * Need to resend pspd coefficients after stream started for
5981 * older kernel version as it does not save the coefficients
5982 * and also stream has to be started for coeff to apply.
5983 */
5984 usecase = get_usecase_from_list(adev, out->usecase);
5985 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305986 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305987 out->pspd_coeff_sent = true;
5988 }
5989 }
5990
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005991 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005992 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005993 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005994 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005995 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5996 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305997 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5998 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005999 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306000 out->send_next_track_params = false;
6001 out->is_compr_metadata_avail = false;
6002 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006003 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306004 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306005 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006006
Ashish Jain83a6cc22016-06-28 14:34:17 +05306007 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306008 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306009 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306010 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006011 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306012 return -EINVAL;
6013 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306014 audio_format_t dst_format = out->hal_op_format;
6015 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306016
Dieter Luecking5d57def2018-09-07 14:23:37 +02006017 /* prevent division-by-zero */
6018 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6019 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6020 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6021 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306022 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006023 ATRACE_END();
6024 return -EINVAL;
6025 }
6026
Ashish Jainf1eaa582016-05-23 20:54:24 +05306027 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6028 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6029
Ashish Jain83a6cc22016-06-28 14:34:17 +05306030 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306031 dst_format,
6032 buffer,
6033 src_format,
6034 frames);
6035
Ashish Jain83a6cc22016-06-28 14:34:17 +05306036 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306037 bytes_to_write);
6038
6039 /*Convert written bytes in audio flinger format*/
6040 if (ret > 0)
6041 ret = ((ret * format_to_bitwidth_table[out->format]) /
6042 format_to_bitwidth_table[dst_format]);
6043 }
6044 } else
6045 ret = compress_write(out->compr, buffer, bytes);
6046
Zhou Songc9672822017-08-16 16:01:39 +08006047 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6048 update_frames_written(out, bytes);
6049
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306050 if (ret < 0)
6051 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006052 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306053 /*msg to cb thread only if non blocking write is enabled*/
6054 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306055 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006056 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306057 } else if (-ENETRESET == ret) {
6058 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306059 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306060 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306061 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006062 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306063 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006064 }
Ashish Jain5106d362016-05-11 19:23:33 +05306065
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306066 /* Call compr start only when non-zero bytes of data is there to be rendered */
6067 if (!out->playback_started && ret > 0) {
6068 int status = compress_start(out->compr);
6069 if (status < 0) {
6070 ret = status;
6071 ALOGE("%s: compr start failed with err %d", __func__, errno);
6072 goto exit;
6073 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006074 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006075 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006076 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006077 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006078 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006079
6080 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6081 popcount(out->channel_mask),
6082 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006083 }
6084 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006085 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006086 return ret;
6087 } else {
6088 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006089 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006090 if (out->muted)
6091 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006092 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6093 __func__, frames, frame_size, bytes_to_write);
6094
Aalique Grahame22e49102018-12-18 14:23:57 -08006095 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006096 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6097 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6098 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006099 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6100 int16_t *src = (int16_t *)buffer;
6101 int16_t *dst = (int16_t *)buffer;
6102
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006103 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006104 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006105 "out_write called for %s use case with wrong properties",
6106 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006107
6108 /*
6109 * FIXME: this can be removed once audio flinger mixer supports
6110 * mono output
6111 */
6112
6113 /*
6114 * Code below goes over each frame in the buffer and adds both
6115 * L and R samples and then divides by 2 to convert to mono
6116 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006117 if (channel_count == 2) {
6118 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6119 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6120 }
6121 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006122 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006123 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006124
6125 // Note: since out_get_presentation_position() is called alternating with out_write()
6126 // by AudioFlinger, we can check underruns using the prior timestamp read.
6127 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6128 if (out->last_fifo_valid) {
6129 // compute drain to see if there is an underrun.
6130 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306131 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6132 int64_t frames_by_time =
6133 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6134 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006135 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6136
6137 if (underrun > 0) {
6138 simple_stats_log(&out->fifo_underruns, underrun);
6139
6140 ALOGW("%s: underrun(%lld) "
6141 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6142 __func__,
6143 (long long)out->fifo_underruns.n,
6144 (long long)frames_by_time,
6145 (long long)out->last_fifo_frames_remaining);
6146 }
6147 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6148 }
6149
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306150 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006151
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006152 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006153
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006154 if (out->config.rate)
6155 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6156 out->config.rate;
6157
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006158 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006159 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6160
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006161 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006162 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006163 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306164 out->convert_buffer != NULL) {
6165
6166 memcpy_by_audio_format(out->convert_buffer,
6167 out->hal_op_format,
6168 buffer,
6169 out->hal_ip_format,
6170 out->config.period_size * out->config.channels);
6171
6172 ret = pcm_write(out->pcm, out->convert_buffer,
6173 (out->config.period_size *
6174 out->config.channels *
6175 format_to_bitwidth_table[out->hal_op_format]));
6176 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306177 /*
6178 * To avoid underrun in DSP when the application is not pumping
6179 * data at required rate, check for the no. of bytes and ignore
6180 * pcm_write if it is less than actual buffer size.
6181 * It is a work around to a change in compress VOIP driver.
6182 */
6183 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6184 bytes < (out->config.period_size * out->config.channels *
6185 audio_bytes_per_sample(out->format))) {
6186 size_t voip_buf_size =
6187 out->config.period_size * out->config.channels *
6188 audio_bytes_per_sample(out->format);
6189 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6190 __func__, bytes, voip_buf_size);
6191 usleep(((uint64_t)voip_buf_size - bytes) *
6192 1000000 / audio_stream_out_frame_size(stream) /
6193 out_get_sample_rate(&out->stream.common));
6194 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006195 } else {
6196 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6197 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6198 else
6199 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6200 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306201 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006202
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006203 release_out_focus(out);
6204
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306205 if (ret < 0)
6206 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006207 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306208 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006209 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210 }
6211
6212exit:
Zhou Songc9672822017-08-16 16:01:39 +08006213 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306214 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306215 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306216 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006217 pthread_mutex_unlock(&out->lock);
6218
6219 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006220 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006221 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306222 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306223 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306224 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306225 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306226 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306227 out->standby = true;
6228 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306229 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006230 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6231 /* prevent division-by-zero */
6232 uint32_t stream_size = audio_stream_out_frame_size(stream);
6233 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006234
Dieter Luecking5d57def2018-09-07 14:23:37 +02006235 if ((stream_size == 0) || (srate == 0)) {
6236 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6237 ATRACE_END();
6238 return -EINVAL;
6239 }
6240 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6241 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006242 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306243 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006244 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006245 return ret;
6246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006247 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006248 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006249 return bytes;
6250}
6251
6252static int out_get_render_position(const struct audio_stream_out *stream,
6253 uint32_t *dsp_frames)
6254{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006255 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006256
6257 if (dsp_frames == NULL)
6258 return -EINVAL;
6259
6260 *dsp_frames = 0;
6261 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006262 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306263
6264 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6265 * this operation and adev_close_output_stream(where out gets reset).
6266 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306267 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006268 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306269 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006270 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306271 return 0;
6272 }
6273
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006274 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306275 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306276 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006277 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306278 if (ret < 0)
6279 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006280 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306281 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006282 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306283 if (-ENETRESET == ret) {
6284 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306285 out->card_status = CARD_STATUS_OFFLINE;
6286 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306287 } else if(ret < 0) {
6288 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306289 ret = -EINVAL;
6290 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306291 /*
6292 * Handle corner case where compress session is closed during SSR
6293 * and timestamp is queried
6294 */
6295 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306296 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306297 } else if (out->prev_card_status_offline) {
6298 ALOGE("ERROR: previously sound card was offline,return error");
6299 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306300 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306301 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006302 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306303 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306304 pthread_mutex_unlock(&out->lock);
6305 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006306 } else if (audio_is_linear_pcm(out->format)) {
6307 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006308 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006309 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006310 } else
6311 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006312}
6313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006314static int out_add_audio_effect(const struct audio_stream *stream __unused,
6315 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006316{
6317 return 0;
6318}
6319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006320static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6321 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006322{
6323 return 0;
6324}
6325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006326static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6327 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006328{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306329 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006330}
6331
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006332static int out_get_presentation_position(const struct audio_stream_out *stream,
6333 uint64_t *frames, struct timespec *timestamp)
6334{
6335 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306336 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006337 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006338
Ashish Jain5106d362016-05-11 19:23:33 +05306339 /* below piece of code is not guarded against any lock because audioFliner serializes
6340 * this operation and adev_close_output_stream( where out gets reset).
6341 */
6342 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306343 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006344 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306345 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6346 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6347 return 0;
6348 }
6349
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006350 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006351
Ashish Jain5106d362016-05-11 19:23:33 +05306352 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6353 ret = compress_get_tstamp(out->compr, &dsp_frames,
6354 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006355 // Adjustment accounts for A2dp encoder latency with offload usecases
6356 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006357 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006358 unsigned long offset =
6359 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6360 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6361 }
Ashish Jain5106d362016-05-11 19:23:33 +05306362 ALOGVV("%s rendered frames %ld sample_rate %d",
6363 __func__, dsp_frames, out->sample_rate);
6364 *frames = dsp_frames;
6365 if (ret < 0)
6366 ret = -errno;
6367 if (-ENETRESET == ret) {
6368 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306369 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306370 ret = -EINVAL;
6371 } else
6372 ret = 0;
6373 /* this is the best we can do */
6374 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006375 } else {
6376 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006377 unsigned int avail;
6378 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006379 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006380 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006381
Andy Hunga1f48fa2019-07-01 18:14:53 -07006382 if (out->kernel_buffer_size > avail) {
6383 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6384 } else {
6385 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6386 __func__, avail, out->kernel_buffer_size);
6387 avail = out->kernel_buffer_size;
6388 frames_temp = out->last_fifo_frames_remaining = 0;
6389 }
6390 out->last_fifo_valid = true;
6391 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6392
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006393 if (out->written >= frames_temp)
6394 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006395
Andy Hunga1f48fa2019-07-01 18:14:53 -07006396 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6397 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6398
Weiyin Jiangd4633762018-03-16 12:05:03 +08006399 // This adjustment accounts for buffering after app processor.
6400 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006401 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006402 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006403 if (signed_frames >= frames_temp)
6404 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006405
Weiyin Jiangd4633762018-03-16 12:05:03 +08006406 // Adjustment accounts for A2dp encoder latency with non offload usecases
6407 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006408 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006409 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6410 if (signed_frames >= frames_temp)
6411 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006412 }
6413
6414 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006415 *frames = signed_frames;
6416 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006417 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006418 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6419 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006420 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306421 *frames = out->written;
6422 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306423 if (is_offload_usecase(out->usecase))
6424 ret = -EINVAL;
6425 else
6426 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006427 }
6428 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006429 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006430 return ret;
6431}
6432
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006433static int out_set_callback(struct audio_stream_out *stream,
6434 stream_callback_t callback, void *cookie)
6435{
6436 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006437 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006438
6439 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006440 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006441 out->client_callback = callback;
6442 out->client_cookie = cookie;
6443 if (out->adsp_hdlr_stream_handle) {
6444 ret = audio_extn_adsp_hdlr_stream_set_callback(
6445 out->adsp_hdlr_stream_handle,
6446 callback,
6447 cookie);
6448 if (ret)
6449 ALOGW("%s:adsp hdlr callback registration failed %d",
6450 __func__, ret);
6451 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006452 pthread_mutex_unlock(&out->lock);
6453 return 0;
6454}
6455
6456static int out_pause(struct audio_stream_out* stream)
6457{
6458 struct stream_out *out = (struct stream_out *)stream;
6459 int status = -ENOSYS;
6460 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006461 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006462 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306463 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006464 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006465 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006466 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306467 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306468 status = compress_pause(out->compr);
6469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006470 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006471
Mingming Yin21854652016-04-13 11:54:02 -07006472 if (audio_extn_passthru_is_active()) {
6473 ALOGV("offload use case, pause passthru");
6474 audio_extn_passthru_on_pause(out);
6475 }
6476
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306477 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006478 audio_extn_dts_notify_playback_state(out->usecase, 0,
6479 out->sample_rate, popcount(out->channel_mask),
6480 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006481 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006482 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006483 pthread_mutex_unlock(&out->lock);
6484 }
6485 return status;
6486}
6487
6488static int out_resume(struct audio_stream_out* stream)
6489{
6490 struct stream_out *out = (struct stream_out *)stream;
6491 int status = -ENOSYS;
6492 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006493 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006494 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306495 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006496 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006497 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006498 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306499 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306500 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006501 }
6502 if (!status) {
6503 out->offload_state = OFFLOAD_STATE_PLAYING;
6504 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306505 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006506 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6507 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006508 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006509 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006510 pthread_mutex_unlock(&out->lock);
6511 }
6512 return status;
6513}
6514
6515static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6516{
6517 struct stream_out *out = (struct stream_out *)stream;
6518 int status = -ENOSYS;
6519 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006520 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006521 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006522 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6523 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6524 else
6525 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6526 pthread_mutex_unlock(&out->lock);
6527 }
6528 return status;
6529}
6530
6531static int out_flush(struct audio_stream_out* stream)
6532{
6533 struct stream_out *out = (struct stream_out *)stream;
6534 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006535 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006536 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006537 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006538 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006539 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306540 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006541 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006542 } else {
6543 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306544 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006545 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006546 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006547 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006548 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006549 return 0;
6550 }
6551 return -ENOSYS;
6552}
6553
Haynes Mathew George16081042017-05-31 17:16:49 -07006554static int out_stop(const struct audio_stream_out* stream)
6555{
6556 struct stream_out *out = (struct stream_out *)stream;
6557 struct audio_device *adev = out->dev;
6558 int ret = -ENOSYS;
6559
6560 ALOGV("%s", __func__);
6561 pthread_mutex_lock(&adev->lock);
6562 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6563 out->playback_started && out->pcm != NULL) {
6564 pcm_stop(out->pcm);
6565 ret = stop_output_stream(out);
6566 out->playback_started = false;
6567 }
6568 pthread_mutex_unlock(&adev->lock);
6569 return ret;
6570}
6571
6572static int out_start(const struct audio_stream_out* stream)
6573{
6574 struct stream_out *out = (struct stream_out *)stream;
6575 struct audio_device *adev = out->dev;
6576 int ret = -ENOSYS;
6577
6578 ALOGV("%s", __func__);
6579 pthread_mutex_lock(&adev->lock);
6580 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6581 !out->playback_started && out->pcm != NULL) {
6582 ret = start_output_stream(out);
6583 if (ret == 0) {
6584 out->playback_started = true;
6585 }
6586 }
6587 pthread_mutex_unlock(&adev->lock);
6588 return ret;
6589}
6590
6591/*
6592 * Modify config->period_count based on min_size_frames
6593 */
6594static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6595{
6596 int periodCountRequested = (min_size_frames + config->period_size - 1)
6597 / config->period_size;
6598 int periodCount = MMAP_PERIOD_COUNT_MIN;
6599
6600 ALOGV("%s original config.period_size = %d config.period_count = %d",
6601 __func__, config->period_size, config->period_count);
6602
6603 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6604 periodCount *= 2;
6605 }
6606 config->period_count = periodCount;
6607
6608 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6609}
6610
Phil Burkfe17efd2019-03-25 10:23:35 -07006611// Read offset for the positional timestamp from a persistent vendor property.
6612// This is to workaround apparent inaccuracies in the timing information that
6613// is used by the AAudio timing model. The inaccuracies can cause glitches.
6614static int64_t get_mmap_out_time_offset() {
6615 const int32_t kDefaultOffsetMicros = 0;
6616 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006617 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006618 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6619 return mmap_time_offset_micros * (int64_t)1000;
6620}
6621
Haynes Mathew George16081042017-05-31 17:16:49 -07006622static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6623 int32_t min_size_frames,
6624 struct audio_mmap_buffer_info *info)
6625{
6626 struct stream_out *out = (struct stream_out *)stream;
6627 struct audio_device *adev = out->dev;
6628 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006629 unsigned int offset1 = 0;
6630 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006631 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006632 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006633 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006634
Arun Mirpuri5d170872019-03-26 13:21:31 -07006635 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306636 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006637 pthread_mutex_lock(&adev->lock);
6638
Sharad Sanglec6f32552018-05-04 16:15:38 +05306639 if (CARD_STATUS_OFFLINE == out->card_status ||
6640 CARD_STATUS_OFFLINE == adev->card_status) {
6641 ALOGW("out->card_status or adev->card_status offline, try again");
6642 ret = -EIO;
6643 goto exit;
6644 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306645 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006646 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6647 ret = -EINVAL;
6648 goto exit;
6649 }
6650 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6651 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6652 ret = -ENOSYS;
6653 goto exit;
6654 }
6655 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6656 if (out->pcm_device_id < 0) {
6657 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6658 __func__, out->pcm_device_id, out->usecase);
6659 ret = -EINVAL;
6660 goto exit;
6661 }
6662
6663 adjust_mmap_period_count(&out->config, min_size_frames);
6664
Arun Mirpuri5d170872019-03-26 13:21:31 -07006665 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006666 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6667 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6668 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306669 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306670 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6671 out->card_status = CARD_STATUS_OFFLINE;
6672 adev->card_status = CARD_STATUS_OFFLINE;
6673 ret = -EIO;
6674 goto exit;
6675 }
6676
Haynes Mathew George16081042017-05-31 17:16:49 -07006677 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6678 step = "open";
6679 ret = -ENODEV;
6680 goto exit;
6681 }
6682 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6683 if (ret < 0) {
6684 step = "begin";
6685 goto exit;
6686 }
juyuchen626833d2019-06-04 16:48:02 +08006687
6688 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006689 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006690 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006691 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006692 ret = platform_get_mmap_data_fd(adev->platform,
6693 out->pcm_device_id, 0 /*playback*/,
6694 &info->shared_memory_fd,
6695 &mmap_size);
6696 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006697 // Fall back to non exclusive mode
6698 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6699 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006700 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6701 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6702
Arun Mirpuri5d170872019-03-26 13:21:31 -07006703 if (mmap_size < buffer_size) {
6704 step = "mmap";
6705 goto exit;
6706 }
juyuchen626833d2019-06-04 16:48:02 +08006707 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006708 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006709 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006710 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006711
6712 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6713 if (ret < 0) {
6714 step = "commit";
6715 goto exit;
6716 }
6717
Phil Burkfe17efd2019-03-25 10:23:35 -07006718 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6719
Haynes Mathew George16081042017-05-31 17:16:49 -07006720 out->standby = false;
6721 ret = 0;
6722
Arun Mirpuri5d170872019-03-26 13:21:31 -07006723 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006724 __func__, info->shared_memory_address, info->buffer_size_frames);
6725
6726exit:
6727 if (ret != 0) {
6728 if (out->pcm == NULL) {
6729 ALOGE("%s: %s - %d", __func__, step, ret);
6730 } else {
6731 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6732 pcm_close(out->pcm);
6733 out->pcm = NULL;
6734 }
6735 }
6736 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306737 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006738 return ret;
6739}
6740
6741static int out_get_mmap_position(const struct audio_stream_out *stream,
6742 struct audio_mmap_position *position)
6743{
6744 struct stream_out *out = (struct stream_out *)stream;
6745 ALOGVV("%s", __func__);
6746 if (position == NULL) {
6747 return -EINVAL;
6748 }
6749 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006750 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006751 return -ENOSYS;
6752 }
6753 if (out->pcm == NULL) {
6754 return -ENOSYS;
6755 }
6756
6757 struct timespec ts = { 0, 0 };
6758 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6759 if (ret < 0) {
6760 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6761 return ret;
6762 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006763 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6764 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006765 return 0;
6766}
6767
6768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006769/** audio_stream_in implementation **/
6770static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6771{
6772 struct stream_in *in = (struct stream_in *)stream;
6773
6774 return in->config.rate;
6775}
6776
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006777static int in_set_sample_rate(struct audio_stream *stream __unused,
6778 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006779{
6780 return -ENOSYS;
6781}
6782
6783static size_t in_get_buffer_size(const struct audio_stream *stream)
6784{
6785 struct stream_in *in = (struct stream_in *)stream;
6786
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006787 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6788 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006789 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6790 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306791 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306792 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006793
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006794 return in->config.period_size * in->af_period_multiplier *
6795 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796}
6797
6798static uint32_t in_get_channels(const struct audio_stream *stream)
6799{
6800 struct stream_in *in = (struct stream_in *)stream;
6801
6802 return in->channel_mask;
6803}
6804
6805static audio_format_t in_get_format(const struct audio_stream *stream)
6806{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006807 struct stream_in *in = (struct stream_in *)stream;
6808
6809 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006810}
6811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006812static int in_set_format(struct audio_stream *stream __unused,
6813 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006814{
6815 return -ENOSYS;
6816}
6817
6818static int in_standby(struct audio_stream *stream)
6819{
6820 struct stream_in *in = (struct stream_in *)stream;
6821 struct audio_device *adev = in->dev;
6822 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306823 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6824 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006825 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306826
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006827 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006828 if (!in->standby && in->is_st_session) {
6829 ALOGD("%s: sound trigger pcm stop lab", __func__);
6830 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006831 if (adev->num_va_sessions > 0)
6832 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006833 in->standby = 1;
6834 }
6835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006837 if (adev->adm_deregister_stream)
6838 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6839
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006840 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006841 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006842 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006843 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006844 voice_extn_compress_voip_close_input_stream(stream);
6845 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006846 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6847 do_stop = in->capture_started;
6848 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006849 if (in->mmap_shared_memory_fd >= 0) {
6850 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6851 __func__, in->mmap_shared_memory_fd);
6852 close(in->mmap_shared_memory_fd);
6853 in->mmap_shared_memory_fd = -1;
6854 }
Zhou Songa8895042016-07-05 17:54:22 +08006855 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306856 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306857 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006858 }
6859
Arun Mirpuri5d170872019-03-26 13:21:31 -07006860 if (in->pcm) {
6861 ATRACE_BEGIN("pcm_in_close");
6862 pcm_close(in->pcm);
6863 ATRACE_END();
6864 in->pcm = NULL;
6865 }
6866
Carter Hsu2e429db2019-05-14 18:50:52 +08006867 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006868 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006869
George Gao3018ede2019-10-23 13:23:00 -07006870 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6871 if (adev->num_va_sessions > 0)
6872 adev->num_va_sessions--;
6873 }
Quinn Malef6050362019-01-30 15:55:40 -08006874
Eric Laurent150dbfe2013-02-27 14:31:02 -08006875 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006876 }
6877 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006878 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006879 return status;
6880}
6881
Aalique Grahame22e49102018-12-18 14:23:57 -08006882static int in_dump(const struct audio_stream *stream,
6883 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006884{
Aalique Grahame22e49102018-12-18 14:23:57 -08006885 struct stream_in *in = (struct stream_in *)stream;
6886
6887 // We try to get the lock for consistency,
6888 // but it isn't necessary for these variables.
6889 // If we're not in standby, we may be blocked on a read.
6890 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6891 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6892 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6893 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6894
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006895 char buffer[256]; // for statistics formatting
6896 if (in->start_latency_ms.n > 0) {
6897 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6898 dprintf(fd, " Start latency ms: %s\n", buffer);
6899 }
6900
Aalique Grahame22e49102018-12-18 14:23:57 -08006901 if (locked) {
6902 pthread_mutex_unlock(&in->lock);
6903 }
6904
6905 // dump error info
6906 (void)error_log_dump(
6907 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006909 return 0;
6910}
6911
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306912static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6913{
6914 if (!stream || !parms)
6915 return;
6916
6917 struct stream_in *in = (struct stream_in *)stream;
6918 struct audio_device *adev = in->dev;
6919
6920 card_status_t status;
6921 int card;
6922 if (parse_snd_card_status(parms, &card, &status) < 0)
6923 return;
6924
6925 pthread_mutex_lock(&adev->lock);
6926 bool valid_cb = (card == adev->snd_card);
6927 pthread_mutex_unlock(&adev->lock);
6928
6929 if (!valid_cb)
6930 return;
6931
6932 lock_input_stream(in);
6933 if (in->card_status != status)
6934 in->card_status = status;
6935 pthread_mutex_unlock(&in->lock);
6936
6937 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6938 use_case_table[in->usecase],
6939 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6940
6941 // a better solution would be to report error back to AF and let
6942 // it put the stream to standby
6943 if (status == CARD_STATUS_OFFLINE)
6944 in_standby(&in->stream.common);
6945
6946 return;
6947}
6948
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006949int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006950 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006951 audio_source_t source)
6952{
6953 struct audio_device *adev = in->dev;
6954 int ret = 0;
6955
6956 lock_input_stream(in);
6957 pthread_mutex_lock(&adev->lock);
6958
6959 /* no audio source uses val == 0 */
6960 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6961 in->source = source;
6962 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6963 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6964 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6965 (in->config.rate == 8000 || in->config.rate == 16000 ||
6966 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6967 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6968 ret = voice_extn_compress_voip_open_input_stream(in);
6969 if (ret != 0) {
6970 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6971 __func__, ret);
6972 }
6973 }
6974 }
6975
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006976 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6977 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006978 // Workaround: If routing to an non existing usb device, fail gracefully
6979 // The routing request will otherwise block during 10 second
6980 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006981 struct str_parms *usb_addr =
6982 str_parms_create_str(get_usb_device_address(devices));
6983 if (is_usb_in_device_type(devices) && usb_addr &&
6984 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006985 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6986 ret = -ENOSYS;
6987 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006988 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006989 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006990 if (!in->standby && !in->is_st_session) {
6991 ALOGV("update input routing change");
6992 // inform adm before actual routing to prevent glitches.
6993 if (adev->adm_on_routing_change) {
6994 adev->adm_on_routing_change(adev->adm_data,
6995 in->capture_handle);
6996 ret = select_devices(adev, in->usecase);
6997 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6998 adev->adm_routing_changed = true;
6999 }
7000 }
7001 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007002 if (usb_addr)
7003 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007004 }
7005 pthread_mutex_unlock(&adev->lock);
7006 pthread_mutex_unlock(&in->lock);
7007
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007008 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007009 return ret;
7010}
7011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007012static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7013{
7014 struct stream_in *in = (struct stream_in *)stream;
7015 struct audio_device *adev = in->dev;
7016 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007017 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307018 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007019
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307020 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007021 parms = str_parms_create_str(kvpairs);
7022
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307023 if (!parms)
7024 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007025 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007026 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007027
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307028 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7029 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307030 strlcpy(in->profile, value, sizeof(in->profile));
7031 ALOGV("updating stream profile with value '%s'", in->profile);
7032 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7033 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007034 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307035 in->sample_rate, in->bit_width,
7036 in->profile, &in->app_type_cfg);
7037 }
7038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007039 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007040 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007041
7042 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307043error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307044 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007045}
7046
7047static char* in_get_parameters(const struct audio_stream *stream,
7048 const char *keys)
7049{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007050 struct stream_in *in = (struct stream_in *)stream;
7051 struct str_parms *query = str_parms_create_str(keys);
7052 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007053 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007054
7055 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007056 if (reply) {
7057 str_parms_destroy(reply);
7058 }
7059 if (query) {
7060 str_parms_destroy(query);
7061 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007062 ALOGE("in_get_parameters: failed to create query or reply");
7063 return NULL;
7064 }
7065
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007066 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007067
7068 voice_extn_in_get_parameters(in, query, reply);
7069
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007070 stream_get_parameter_channels(query, reply,
7071 &in->supported_channel_masks[0]);
7072 stream_get_parameter_formats(query, reply,
7073 &in->supported_formats[0]);
7074 stream_get_parameter_rates(query, reply,
7075 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007076 str = str_parms_to_str(reply);
7077 str_parms_destroy(query);
7078 str_parms_destroy(reply);
7079
7080 ALOGV("%s: exit: returns - %s", __func__, str);
7081 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007082}
7083
Aalique Grahame22e49102018-12-18 14:23:57 -08007084static int in_set_gain(struct audio_stream_in *stream,
7085 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007086{
Aalique Grahame22e49102018-12-18 14:23:57 -08007087 struct stream_in *in = (struct stream_in *)stream;
7088 char mixer_ctl_name[128];
7089 struct mixer_ctl *ctl;
7090 int ctl_value;
7091
7092 ALOGV("%s: gain %f", __func__, gain);
7093
7094 if (stream == NULL)
7095 return -EINVAL;
7096
7097 /* in_set_gain() only used to silence MMAP capture for now */
7098 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7099 return -ENOSYS;
7100
7101 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7102
7103 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7104 if (!ctl) {
7105 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7106 __func__, mixer_ctl_name);
7107 return -ENOSYS;
7108 }
7109
7110 if (gain < RECORD_GAIN_MIN)
7111 gain = RECORD_GAIN_MIN;
7112 else if (gain > RECORD_GAIN_MAX)
7113 gain = RECORD_GAIN_MAX;
7114 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7115
7116 mixer_ctl_set_value(ctl, 0, ctl_value);
7117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007118 return 0;
7119}
7120
7121static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7122 size_t bytes)
7123{
7124 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307125
7126 if (in == NULL) {
7127 ALOGE("%s: stream_in ptr is NULL", __func__);
7128 return -EINVAL;
7129 }
7130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007131 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307132 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307133 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007135 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307136
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007137 if (in->is_st_session) {
7138 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7139 /* Read from sound trigger HAL */
7140 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007141 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007142 if (adev->num_va_sessions < UINT_MAX)
7143 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007144 in->standby = 0;
7145 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007146 pthread_mutex_unlock(&in->lock);
7147 return bytes;
7148 }
7149
Haynes Mathew George16081042017-05-31 17:16:49 -07007150 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7151 ret = -ENOSYS;
7152 goto exit;
7153 }
7154
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007155 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7156 !in->standby && adev->adm_routing_changed) {
7157 ret = -ENOSYS;
7158 goto exit;
7159 }
7160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007161 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007162 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7163
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007164 pthread_mutex_lock(&adev->lock);
7165 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7166 ret = voice_extn_compress_voip_start_input_stream(in);
7167 else
7168 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007169 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7170 if (adev->num_va_sessions < UINT_MAX)
7171 adev->num_va_sessions++;
7172 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007173 pthread_mutex_unlock(&adev->lock);
7174 if (ret != 0) {
7175 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007176 }
7177 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007178
7179 // log startup time in ms.
7180 simple_stats_log(
7181 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007182 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007183
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307184 /* Avoid read if capture_stopped is set */
7185 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7186 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7187 ret = -EINVAL;
7188 goto exit;
7189 }
7190
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007191 // what's the duration requested by the client?
7192 long ns = 0;
7193
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307194 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007195 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7196 in->config.rate;
7197
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007198 ret = request_in_focus(in, ns);
7199 if (ret != 0)
7200 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007201 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007202
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307203 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307204 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7205 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307206 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007207 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307208 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007209 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007210 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007211 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007212 } else if (audio_extn_ffv_get_stream() == in) {
7213 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307214 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007215 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307216 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7217 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7218 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7219 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307220 ret = -EINVAL;
7221 goto exit;
7222 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307223 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307224 ret = -errno;
7225 }
7226 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307227 /* bytes read is always set to bytes for non compress usecases */
7228 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007229 }
7230
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007231 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007233 /*
Quinn Malef6050362019-01-30 15:55:40 -08007234 * Instead of writing zeroes here, we could trust the hardware to always
7235 * provide zeroes when muted. This is also muted with voice recognition
7236 * usecases so that other clients do not have access to voice recognition
7237 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007238 */
Quinn Malef6050362019-01-30 15:55:40 -08007239 if ((ret == 0 && voice_get_mic_mute(adev) &&
7240 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007241 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7242 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007243 (adev->num_va_sessions &&
7244 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7245 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7246 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007247 memset(buffer, 0, bytes);
7248
7249exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307250 frame_size = audio_stream_in_frame_size(stream);
7251 if (frame_size > 0)
7252 in->frames_read += bytes_read/frame_size;
7253
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007254 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307255 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007256 pthread_mutex_unlock(&in->lock);
7257
7258 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307259 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307260 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307261 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307262 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307263 in->standby = true;
7264 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307265 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307266 bytes_read = bytes;
7267 memset(buffer, 0, bytes);
7268 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007269 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007270 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7271 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007272 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307273 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307274 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007275 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307276 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007277}
7278
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007279static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007280{
7281 return 0;
7282}
7283
Aalique Grahame22e49102018-12-18 14:23:57 -08007284static int in_get_capture_position(const struct audio_stream_in *stream,
7285 int64_t *frames, int64_t *time)
7286{
7287 if (stream == NULL || frames == NULL || time == NULL) {
7288 return -EINVAL;
7289 }
7290 struct stream_in *in = (struct stream_in *)stream;
7291 int ret = -ENOSYS;
7292
7293 lock_input_stream(in);
7294 // note: ST sessions do not close the alsa pcm driver synchronously
7295 // on standby. Therefore, we may return an error even though the
7296 // pcm stream is still opened.
7297 if (in->standby) {
7298 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7299 "%s stream in standby but pcm not NULL for non ST session", __func__);
7300 goto exit;
7301 }
7302 if (in->pcm) {
7303 struct timespec timestamp;
7304 unsigned int avail;
7305 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7306 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007307 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007308 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007309 ret = 0;
7310 }
7311 }
7312exit:
7313 pthread_mutex_unlock(&in->lock);
7314 return ret;
7315}
7316
Carter Hsu2e429db2019-05-14 18:50:52 +08007317static int in_update_effect_list(bool add, effect_handle_t effect,
7318 struct listnode *head)
7319{
7320 struct listnode *node;
7321 struct in_effect_list *elist = NULL;
7322 struct in_effect_list *target = NULL;
7323 int ret = 0;
7324
7325 if (!head)
7326 return ret;
7327
7328 list_for_each(node, head) {
7329 elist = node_to_item(node, struct in_effect_list, list);
7330 if (elist->handle == effect) {
7331 target = elist;
7332 break;
7333 }
7334 }
7335
7336 if (add) {
7337 if (target) {
7338 ALOGD("effect %p already exist", effect);
7339 return ret;
7340 }
7341
7342 target = (struct in_effect_list *)
7343 calloc(1, sizeof(struct in_effect_list));
7344
7345 if (!target) {
7346 ALOGE("%s:fail to allocate memory", __func__);
7347 return -ENOMEM;
7348 }
7349
7350 target->handle = effect;
7351 list_add_tail(head, &target->list);
7352 } else {
7353 if (target) {
7354 list_remove(&target->list);
7355 free(target);
7356 }
7357 }
7358
7359 return ret;
7360}
7361
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007362static int add_remove_audio_effect(const struct audio_stream *stream,
7363 effect_handle_t effect,
7364 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007365{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007366 struct stream_in *in = (struct stream_in *)stream;
7367 int status = 0;
7368 effect_descriptor_t desc;
7369
7370 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007371 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7372
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007373 if (status != 0)
7374 return status;
7375
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007376 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007377 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007378 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007379 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7380 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007381 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007382
7383 in_update_effect_list(enable, effect, &in->aec_list);
7384 enable = !list_empty(&in->aec_list);
7385 if (enable == in->enable_aec)
7386 goto exit;
7387
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007388 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007389 ALOGD("AEC enable %d", enable);
7390
Aalique Grahame22e49102018-12-18 14:23:57 -08007391 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7392 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7393 in->dev->enable_voicerx = enable;
7394 struct audio_usecase *usecase;
7395 struct listnode *node;
7396 list_for_each(node, &in->dev->usecase_list) {
7397 usecase = node_to_item(node, struct audio_usecase, list);
7398 if (usecase->type == PCM_PLAYBACK)
7399 select_devices(in->dev, usecase->id);
7400 }
7401 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007402 if (!in->standby) {
7403 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7404 select_devices(in->dev, in->usecase);
7405 }
7406
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007407 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007408 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7409
7410 in_update_effect_list(enable, effect, &in->ns_list);
7411 enable = !list_empty(&in->ns_list);
7412 if (enable == in->enable_ns)
7413 goto exit;
7414
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007415 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007416 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007417 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007418 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7419 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007420 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7421 select_devices(in->dev, in->usecase);
7422 } else
7423 select_devices(in->dev, in->usecase);
7424 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007425 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007426exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007427 pthread_mutex_unlock(&in->dev->lock);
7428 pthread_mutex_unlock(&in->lock);
7429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007430 return 0;
7431}
7432
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007433static int in_add_audio_effect(const struct audio_stream *stream,
7434 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007435{
Eric Laurent994a6932013-07-17 11:51:42 -07007436 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007437 return add_remove_audio_effect(stream, effect, true);
7438}
7439
7440static int in_remove_audio_effect(const struct audio_stream *stream,
7441 effect_handle_t effect)
7442{
Eric Laurent994a6932013-07-17 11:51:42 -07007443 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007444 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007445}
7446
Derek Chenf939fb72018-11-13 13:34:41 -08007447streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7448 audio_io_handle_t input)
7449{
7450 struct listnode *node;
7451
7452 list_for_each(node, &dev->active_inputs_list) {
7453 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7454 streams_input_ctxt_t,
7455 list);
7456 if (in_ctxt->input->capture_handle == input) {
7457 return in_ctxt;
7458 }
7459 }
7460 return NULL;
7461}
7462
7463streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7464 audio_io_handle_t output)
7465{
7466 struct listnode *node;
7467
7468 list_for_each(node, &dev->active_outputs_list) {
7469 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7470 streams_output_ctxt_t,
7471 list);
7472 if (out_ctxt->output->handle == output) {
7473 return out_ctxt;
7474 }
7475 }
7476 return NULL;
7477}
7478
Haynes Mathew George16081042017-05-31 17:16:49 -07007479static int in_stop(const struct audio_stream_in* stream)
7480{
7481 struct stream_in *in = (struct stream_in *)stream;
7482 struct audio_device *adev = in->dev;
7483
7484 int ret = -ENOSYS;
7485 ALOGV("%s", __func__);
7486 pthread_mutex_lock(&adev->lock);
7487 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7488 in->capture_started && in->pcm != NULL) {
7489 pcm_stop(in->pcm);
7490 ret = stop_input_stream(in);
7491 in->capture_started = false;
7492 }
7493 pthread_mutex_unlock(&adev->lock);
7494 return ret;
7495}
7496
7497static int in_start(const struct audio_stream_in* stream)
7498{
7499 struct stream_in *in = (struct stream_in *)stream;
7500 struct audio_device *adev = in->dev;
7501 int ret = -ENOSYS;
7502
7503 ALOGV("%s in %p", __func__, in);
7504 pthread_mutex_lock(&adev->lock);
7505 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7506 !in->capture_started && in->pcm != NULL) {
7507 if (!in->capture_started) {
7508 ret = start_input_stream(in);
7509 if (ret == 0) {
7510 in->capture_started = true;
7511 }
7512 }
7513 }
7514 pthread_mutex_unlock(&adev->lock);
7515 return ret;
7516}
7517
Phil Burke0a86d12019-02-16 22:28:11 -08007518// Read offset for the positional timestamp from a persistent vendor property.
7519// This is to workaround apparent inaccuracies in the timing information that
7520// is used by the AAudio timing model. The inaccuracies can cause glitches.
7521static int64_t in_get_mmap_time_offset() {
7522 const int32_t kDefaultOffsetMicros = 0;
7523 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007524 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007525 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7526 return mmap_time_offset_micros * (int64_t)1000;
7527}
7528
Haynes Mathew George16081042017-05-31 17:16:49 -07007529static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7530 int32_t min_size_frames,
7531 struct audio_mmap_buffer_info *info)
7532{
7533 struct stream_in *in = (struct stream_in *)stream;
7534 struct audio_device *adev = in->dev;
7535 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007536 unsigned int offset1 = 0;
7537 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007538 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007539 uint32_t mmap_size = 0;
7540 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007541
7542 pthread_mutex_lock(&adev->lock);
7543 ALOGV("%s in %p", __func__, in);
7544
Sharad Sanglec6f32552018-05-04 16:15:38 +05307545 if (CARD_STATUS_OFFLINE == in->card_status||
7546 CARD_STATUS_OFFLINE == adev->card_status) {
7547 ALOGW("in->card_status or adev->card_status offline, try again");
7548 ret = -EIO;
7549 goto exit;
7550 }
7551
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307552 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007553 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7554 ret = -EINVAL;
7555 goto exit;
7556 }
7557 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7558 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7559 ALOGV("%s in %p", __func__, in);
7560 ret = -ENOSYS;
7561 goto exit;
7562 }
7563 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7564 if (in->pcm_device_id < 0) {
7565 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7566 __func__, in->pcm_device_id, in->usecase);
7567 ret = -EINVAL;
7568 goto exit;
7569 }
7570
7571 adjust_mmap_period_count(&in->config, min_size_frames);
7572
7573 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7574 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7575 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7576 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307577 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307578 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7579 in->card_status = CARD_STATUS_OFFLINE;
7580 adev->card_status = CARD_STATUS_OFFLINE;
7581 ret = -EIO;
7582 goto exit;
7583 }
7584
Haynes Mathew George16081042017-05-31 17:16:49 -07007585 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7586 step = "open";
7587 ret = -ENODEV;
7588 goto exit;
7589 }
7590
7591 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7592 if (ret < 0) {
7593 step = "begin";
7594 goto exit;
7595 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007596
juyuchen626833d2019-06-04 16:48:02 +08007597 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007598 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7599 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7600 info->burst_size_frames = in->config.period_size;
7601 ret = platform_get_mmap_data_fd(adev->platform,
7602 in->pcm_device_id, 1 /*capture*/,
7603 &info->shared_memory_fd,
7604 &mmap_size);
7605 if (ret < 0) {
7606 // Fall back to non exclusive mode
7607 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7608 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007609 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7610 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7611
Arun Mirpuri5d170872019-03-26 13:21:31 -07007612 if (mmap_size < buffer_size) {
7613 step = "mmap";
7614 goto exit;
7615 }
juyuchen626833d2019-06-04 16:48:02 +08007616 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007617 }
7618
7619 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007620
7621 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7622 if (ret < 0) {
7623 step = "commit";
7624 goto exit;
7625 }
7626
Phil Burke0a86d12019-02-16 22:28:11 -08007627 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7628
Haynes Mathew George16081042017-05-31 17:16:49 -07007629 in->standby = false;
7630 ret = 0;
7631
7632 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7633 __func__, info->shared_memory_address, info->buffer_size_frames);
7634
7635exit:
7636 if (ret != 0) {
7637 if (in->pcm == NULL) {
7638 ALOGE("%s: %s - %d", __func__, step, ret);
7639 } else {
7640 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7641 pcm_close(in->pcm);
7642 in->pcm = NULL;
7643 }
7644 }
7645 pthread_mutex_unlock(&adev->lock);
7646 return ret;
7647}
7648
7649static int in_get_mmap_position(const struct audio_stream_in *stream,
7650 struct audio_mmap_position *position)
7651{
7652 struct stream_in *in = (struct stream_in *)stream;
7653 ALOGVV("%s", __func__);
7654 if (position == NULL) {
7655 return -EINVAL;
7656 }
7657 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7658 return -ENOSYS;
7659 }
7660 if (in->pcm == NULL) {
7661 return -ENOSYS;
7662 }
7663 struct timespec ts = { 0, 0 };
7664 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7665 if (ret < 0) {
7666 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7667 return ret;
7668 }
Phil Burke0a86d12019-02-16 22:28:11 -08007669 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7670 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007671 return 0;
7672}
7673
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307674static int in_get_active_microphones(const struct audio_stream_in *stream,
7675 struct audio_microphone_characteristic_t *mic_array,
7676 size_t *mic_count) {
7677 struct stream_in *in = (struct stream_in *)stream;
7678 struct audio_device *adev = in->dev;
7679 ALOGVV("%s", __func__);
7680
7681 lock_input_stream(in);
7682 pthread_mutex_lock(&adev->lock);
7683 int ret = platform_get_active_microphones(adev->platform,
7684 audio_channel_count_from_in_mask(in->channel_mask),
7685 in->usecase, mic_array, mic_count);
7686 pthread_mutex_unlock(&adev->lock);
7687 pthread_mutex_unlock(&in->lock);
7688
7689 return ret;
7690}
7691
7692static int adev_get_microphones(const struct audio_hw_device *dev,
7693 struct audio_microphone_characteristic_t *mic_array,
7694 size_t *mic_count) {
7695 struct audio_device *adev = (struct audio_device *)dev;
7696 ALOGVV("%s", __func__);
7697
7698 pthread_mutex_lock(&adev->lock);
7699 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7700 pthread_mutex_unlock(&adev->lock);
7701
7702 return ret;
7703}
juyuchendb308c22019-01-21 11:57:17 -07007704
7705static void in_update_sink_metadata(struct audio_stream_in *stream,
7706 const struct sink_metadata *sink_metadata) {
7707
7708 if (stream == NULL
7709 || sink_metadata == NULL
7710 || sink_metadata->tracks == NULL) {
7711 return;
7712 }
7713
7714 int error = 0;
7715 struct stream_in *in = (struct stream_in *)stream;
7716 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007717 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007718 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007719
7720 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007721
7722 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007723 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007724
7725 lock_input_stream(in);
7726 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007727 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007728
Zhou Song62ea0282020-03-22 19:53:01 +08007729 is_ha_usecase = adev->ha_proxy_enable ?
7730 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7731 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7732 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007733 && adev->voice_tx_output != NULL) {
7734 /* Use the rx device from afe-proxy record to route voice call because
7735 there is no routing if tx device is on primary hal and rx device
7736 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007737 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007738
7739 if (!voice_is_call_state_active(adev)) {
7740 if (adev->mode == AUDIO_MODE_IN_CALL) {
7741 adev->current_call_output = adev->voice_tx_output;
7742 error = voice_start_call(adev);
7743 if (error != 0)
7744 ALOGE("%s: start voice call failed %d", __func__, error);
7745 }
7746 } else {
7747 adev->current_call_output = adev->voice_tx_output;
7748 voice_update_devices_for_all_voice_usecases(adev);
7749 }
7750 }
7751
7752 pthread_mutex_unlock(&adev->lock);
7753 pthread_mutex_unlock(&in->lock);
7754}
7755
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307756int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007757 audio_io_handle_t handle,
7758 audio_devices_t devices,
7759 audio_output_flags_t flags,
7760 struct audio_config *config,
7761 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007762 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007763{
7764 struct audio_device *adev = (struct audio_device *)dev;
7765 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307766 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007767 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007768 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307769 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007770 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7771 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7772 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7773 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007774 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007775 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7776 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007777 bool force_haptic_path =
7778 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007779 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007780#ifdef AUDIO_GKI_ENABLED
7781 __s32 *generic_dec;
7782#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007783
kunleizdff872d2018-08-20 14:40:33 +08007784 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007785 is_usb_dev = false;
7786 devices = AUDIO_DEVICE_OUT_SPEAKER;
7787 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7788 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007789 if (config->format == AUDIO_FORMAT_DEFAULT)
7790 config->format = AUDIO_FORMAT_PCM_16_BIT;
7791 if (config->sample_rate == 0)
7792 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7793 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7794 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007795 }
7796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007797 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307798
Rahul Sharma99770982019-03-06 17:05:26 +05307799 pthread_mutex_lock(&adev->lock);
7800 if (out_get_stream(adev, handle) != NULL) {
7801 ALOGW("%s, output stream already opened", __func__);
7802 ret = -EEXIST;
7803 }
7804 pthread_mutex_unlock(&adev->lock);
7805 if (ret)
7806 return ret;
7807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007808 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7809
Mingming Yin3a941d42016-02-17 18:08:05 -08007810 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007811 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7812 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307813
7814
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007815 if (!out) {
7816 return -ENOMEM;
7817 }
7818
Haynes Mathew George204045b2015-02-25 20:32:03 -08007819 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007820 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang280ea742020-09-08 20:28:22 +08007821 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007822 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007823 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007825 if (devices == AUDIO_DEVICE_NONE)
7826 devices = AUDIO_DEVICE_OUT_SPEAKER;
7827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007828 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007829 list_init(&out->device_list);
7830 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007831 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007832 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007833 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307834 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307835 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7836 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7837 else
7838 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007839 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007840 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007841 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307842 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307843 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007844 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007845 out->hal_output_suspend_supported = 0;
7846 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307847 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307848 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307849 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007850 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007851
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307852 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307853 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007854 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7855
Aalique Grahame22e49102018-12-18 14:23:57 -08007856 if (direct_dev &&
7857 (audio_is_linear_pcm(out->format) ||
7858 config->format == AUDIO_FORMAT_DEFAULT) &&
7859 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7860 audio_format_t req_format = config->format;
7861 audio_channel_mask_t req_channel_mask = config->channel_mask;
7862 uint32_t req_sample_rate = config->sample_rate;
7863
7864 pthread_mutex_lock(&adev->lock);
7865 if (is_hdmi) {
7866 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7867 ret = read_hdmi_sink_caps(out);
7868 if (config->sample_rate == 0)
7869 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7870 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7871 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7872 if (config->format == AUDIO_FORMAT_DEFAULT)
7873 config->format = AUDIO_FORMAT_PCM_16_BIT;
7874 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007875 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7876 &config->format,
7877 &out->supported_formats[0],
7878 MAX_SUPPORTED_FORMATS,
7879 &config->channel_mask,
7880 &out->supported_channel_masks[0],
7881 MAX_SUPPORTED_CHANNEL_MASKS,
7882 &config->sample_rate,
7883 &out->supported_sample_rates[0],
7884 MAX_SUPPORTED_SAMPLE_RATES);
7885 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007886 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007887
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007888 pthread_mutex_unlock(&adev->lock);
7889 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007890 if (ret == -ENOSYS) {
7891 /* ignore and go with default */
7892 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007893 }
7894 // For MMAP NO IRQ, allow conversions in ADSP
7895 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7896 goto error_open;
7897 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007898 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007899 goto error_open;
7900 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007901
7902 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7903 config->sample_rate = req_sample_rate;
7904 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7905 config->channel_mask = req_channel_mask;
7906 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7907 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007908 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007909
7910 out->sample_rate = config->sample_rate;
7911 out->channel_mask = config->channel_mask;
7912 out->format = config->format;
7913 if (is_hdmi) {
7914 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7915 out->config = pcm_config_hdmi_multi;
7916 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7917 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7918 out->config = pcm_config_mmap_playback;
7919 out->stream.start = out_start;
7920 out->stream.stop = out_stop;
7921 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7922 out->stream.get_mmap_position = out_get_mmap_position;
7923 } else {
7924 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7925 out->config = pcm_config_hifi;
7926 }
7927
7928 out->config.rate = out->sample_rate;
7929 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7930 if (is_hdmi) {
7931 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7932 audio_bytes_per_sample(out->format));
7933 }
7934 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007935 }
7936
Derek Chenf6318be2017-06-12 17:16:24 -04007937 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007938 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007939 /* extract car audio stream index */
7940 out->car_audio_stream =
7941 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7942 if (out->car_audio_stream < 0) {
7943 ALOGE("%s: invalid car audio stream %x",
7944 __func__, out->car_audio_stream);
7945 ret = -EINVAL;
7946 goto error_open;
7947 }
Derek Chen5f67a942020-02-24 23:08:13 -08007948 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007949 }
7950
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007951 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007952 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007953 if (!voice_extn_is_compress_voip_supported()) {
7954 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7955 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007956 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307957 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007958 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7959 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007960 out->volume_l = INVALID_OUT_VOLUME;
7961 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007962
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007963 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007964 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007965 uint32_t channel_count =
7966 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307967 out->config.channels = channel_count;
7968
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007969 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7970 out->sample_rate, out->format,
7971 channel_count, false);
7972 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7973 if (frame_size != 0)
7974 out->config.period_size = buffer_size / frame_size;
7975 else
7976 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007977 }
7978 } else {
7979 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7980 voice_extn_compress_voip_is_active(out->dev)) &&
7981 (voice_extn_compress_voip_is_config_supported(config))) {
7982 ret = voice_extn_compress_voip_open_output_stream(out);
7983 if (ret != 0) {
7984 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7985 __func__, ret);
7986 goto error_open;
7987 }
Sujin Panicker19027262019-09-16 18:28:06 +05307988 } else {
7989 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7990 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007991 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007992 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007993 } else if (audio_is_linear_pcm(out->format) &&
7994 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7995 out->channel_mask = config->channel_mask;
7996 out->sample_rate = config->sample_rate;
7997 out->format = config->format;
7998 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7999 // does this change?
8000 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8001 out->config.rate = config->sample_rate;
8002 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8003 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8004 audio_bytes_per_sample(config->format));
8005 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008006 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308007 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308008 pthread_mutex_lock(&adev->lock);
8009 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8010 pthread_mutex_unlock(&adev->lock);
8011
8012 // reject offload during card offline to allow
8013 // fallback to s/w paths
8014 if (offline) {
8015 ret = -ENODEV;
8016 goto error_open;
8017 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008018
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008019 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8020 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8021 ALOGE("%s: Unsupported Offload information", __func__);
8022 ret = -EINVAL;
8023 goto error_open;
8024 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008025
Atul Khare3fa6e542017-08-09 00:56:17 +05308026 if (config->offload_info.format == 0)
8027 config->offload_info.format = config->format;
8028 if (config->offload_info.sample_rate == 0)
8029 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008030
Mingming Yin90310102013-11-13 16:57:00 -08008031 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308032 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008033 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008034 ret = -EINVAL;
8035 goto error_open;
8036 }
8037
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008038 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8039 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8040 (audio_extn_passthru_is_passthrough_stream(out)) &&
8041 !((config->sample_rate == 48000) ||
8042 (config->sample_rate == 96000) ||
8043 (config->sample_rate == 192000))) {
8044 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8045 __func__, config->sample_rate, config->offload_info.format);
8046 ret = -EINVAL;
8047 goto error_open;
8048 }
8049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 out->compr_config.codec = (struct snd_codec *)
8051 calloc(1, sizeof(struct snd_codec));
8052
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008053 if (!out->compr_config.codec) {
8054 ret = -ENOMEM;
8055 goto error_open;
8056 }
8057
Dhananjay Kumarac341582017-02-23 23:42:25 +05308058 out->stream.pause = out_pause;
8059 out->stream.resume = out_resume;
8060 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308061 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308062 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008063 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308064 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008065 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308066 } else {
8067 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8068 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008069 }
vivek mehta446c3962015-09-14 10:57:35 -07008070
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308071 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8072 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008073#ifdef AUDIO_GKI_ENABLED
8074 /* out->compr_config.codec->reserved[1] is for flags */
8075 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8076#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308077 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008078#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308079 }
8080
vivek mehta446c3962015-09-14 10:57:35 -07008081 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008082 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008083 config->format == 0 && config->sample_rate == 0 &&
8084 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008085 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008086 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8087 } else {
8088 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8089 ret = -EEXIST;
8090 goto error_open;
8091 }
vivek mehta446c3962015-09-14 10:57:35 -07008092 }
8093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008094 if (config->offload_info.channel_mask)
8095 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008096 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008097 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008098 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008099 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308100 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008101 ret = -EINVAL;
8102 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008103 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008104
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008105 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008106 out->sample_rate = config->offload_info.sample_rate;
8107
Mingming Yin3ee55c62014-08-04 14:23:35 -07008108 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008109
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308110 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308111 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308112 audio_extn_dolby_send_ddp_endp_params(adev);
8113 audio_extn_dolby_set_dmid(adev);
8114 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008115
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008116 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008117 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008118 out->compr_config.codec->bit_rate =
8119 config->offload_info.bit_rate;
8120 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308121 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008122 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308123 /* Update bit width only for non passthrough usecases.
8124 * For passthrough usecases, the output will always be opened @16 bit
8125 */
8126 if (!audio_extn_passthru_is_passthrough_stream(out))
8127 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308128
8129 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008130#ifdef AUDIO_GKI_ENABLED
8131 /* out->compr_config.codec->reserved[1] is for flags */
8132 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8133 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8134#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308135 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8136 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008137#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308138
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008139 /*TODO: Do we need to change it for passthrough */
8140 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008141
Manish Dewangana6fc5442015-08-24 20:30:31 +05308142 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8143 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308144 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308145 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308146 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8147 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308148
8149 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8150 AUDIO_FORMAT_PCM) {
8151
8152 /*Based on platform support, configure appropriate alsa format for corresponding
8153 *hal input format.
8154 */
8155 out->compr_config.codec->format = hal_format_to_alsa(
8156 config->offload_info.format);
8157
Ashish Jain83a6cc22016-06-28 14:34:17 +05308158 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308159 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308160 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308161
Dhananjay Kumarac341582017-02-23 23:42:25 +05308162 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308163 *hal input format and alsa format might differ based on platform support.
8164 */
8165 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308166 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308167
8168 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8169
Deeraj Soman93155a62019-09-30 19:00:37 +05308170 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8171 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8172 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8173 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8174 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308175
Ashish Jainf1eaa582016-05-23 20:54:24 +05308176 /* Check if alsa session is configured with the same format as HAL input format,
8177 * if not then derive correct fragment size needed to accomodate the
8178 * conversion of HAL input format to alsa format.
8179 */
8180 audio_extn_utils_update_direct_pcm_fragment_size(out);
8181
8182 /*if hal input and output fragment size is different this indicates HAL input format is
8183 *not same as the alsa format
8184 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308185 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308186 /*Allocate a buffer to convert input data to the alsa configured format.
8187 *size of convert buffer is equal to the size required to hold one fragment size
8188 *worth of pcm data, this is because flinger does not write more than fragment_size
8189 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308190 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8191 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308192 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8193 ret = -ENOMEM;
8194 goto error_open;
8195 }
8196 }
8197 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8198 out->compr_config.fragment_size =
8199 audio_extn_passthru_get_buffer_size(&config->offload_info);
8200 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8201 } else {
8202 out->compr_config.fragment_size =
8203 platform_get_compress_offload_buffer_size(&config->offload_info);
8204 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8205 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008206
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308207 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8208 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8209 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008210 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8211#ifdef AUDIO_GKI_ENABLED
8212 generic_dec =
8213 &(out->compr_config.codec->options.generic.reserved[1]);
8214 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8215 AUDIO_OUTPUT_BIT_WIDTH;
8216#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308217 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008218#endif
8219 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008220
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308221 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8222 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8223 }
8224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008225 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8226 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008227
Manish Dewangan69426c82017-01-30 17:35:36 +05308228 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8229 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8230 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8231 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8232 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8233 } else {
8234 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8235 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008236
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308237 memset(&out->channel_map_param, 0,
8238 sizeof(struct audio_out_channel_map_param));
8239
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008240 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308241 out->send_next_track_params = false;
8242 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008243 out->offload_state = OFFLOAD_STATE_IDLE;
8244 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008245 out->writeAt.tv_sec = 0;
8246 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008247
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008248 audio_extn_dts_create_state_notifier_node(out->usecase);
8249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008250 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8251 __func__, config->offload_info.version,
8252 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308253
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308254 /* Check if DSD audio format is supported in codec
8255 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308256 */
8257
8258 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308259 (!platform_check_codec_dsd_support(adev->platform) ||
8260 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308261 ret = -EINVAL;
8262 goto error_open;
8263 }
8264
Ashish Jain5106d362016-05-11 19:23:33 +05308265 /* Disable gapless if any of the following is true
8266 * passthrough playback
8267 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308268 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308269 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308270 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308271 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008272 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308273 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308274 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308275 check_and_set_gapless_mode(adev, false);
8276 } else
8277 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008278
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308279 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008280 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8281 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308282 if (config->format == AUDIO_FORMAT_DSD) {
8283 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008284#ifdef AUDIO_GKI_ENABLED
8285 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8286 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8287#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308288 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008289#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308290 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008291
8292 create_offload_callback_thread(out);
8293
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008294 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008295 switch (config->sample_rate) {
8296 case 0:
8297 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8298 break;
8299 case 8000:
8300 case 16000:
8301 case 48000:
8302 out->sample_rate = config->sample_rate;
8303 break;
8304 default:
8305 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8306 config->sample_rate);
8307 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8308 ret = -EINVAL;
8309 goto error_open;
8310 }
8311 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8312 switch (config->channel_mask) {
8313 case AUDIO_CHANNEL_NONE:
8314 case AUDIO_CHANNEL_OUT_STEREO:
8315 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8316 break;
8317 default:
8318 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8319 config->channel_mask);
8320 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8321 ret = -EINVAL;
8322 goto error_open;
8323 }
8324 switch (config->format) {
8325 case AUDIO_FORMAT_DEFAULT:
8326 case AUDIO_FORMAT_PCM_16_BIT:
8327 out->format = AUDIO_FORMAT_PCM_16_BIT;
8328 break;
8329 default:
8330 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8331 config->format);
8332 config->format = AUDIO_FORMAT_PCM_16_BIT;
8333 ret = -EINVAL;
8334 goto error_open;
8335 }
8336
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308337 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008338 if (ret != 0) {
8339 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008340 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008341 goto error_open;
8342 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008343 } else if (is_single_device_type_equal(&out->device_list,
8344 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008345 switch (config->sample_rate) {
8346 case 0:
8347 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8348 break;
8349 case 8000:
8350 case 16000:
8351 case 48000:
8352 out->sample_rate = config->sample_rate;
8353 break;
8354 default:
8355 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8356 config->sample_rate);
8357 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8358 ret = -EINVAL;
8359 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008360 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008361 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8362 switch (config->channel_mask) {
8363 case AUDIO_CHANNEL_NONE:
8364 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8365 break;
8366 case AUDIO_CHANNEL_OUT_STEREO:
8367 out->channel_mask = config->channel_mask;
8368 break;
8369 default:
8370 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8371 config->channel_mask);
8372 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8373 ret = -EINVAL;
8374 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008375 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008376 switch (config->format) {
8377 case AUDIO_FORMAT_DEFAULT:
8378 out->format = AUDIO_FORMAT_PCM_16_BIT;
8379 break;
8380 case AUDIO_FORMAT_PCM_16_BIT:
8381 out->format = config->format;
8382 break;
8383 default:
8384 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8385 config->format);
8386 config->format = AUDIO_FORMAT_PCM_16_BIT;
8387 ret = -EINVAL;
8388 break;
8389 }
8390 if (ret != 0)
8391 goto error_open;
8392
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008393 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8394 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008395 out->config.rate = out->sample_rate;
8396 out->config.channels =
8397 audio_channel_count_from_out_mask(out->channel_mask);
8398 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008399 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008400 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308401 unsigned int channels = 0;
8402 /*Update config params to default if not set by the caller*/
8403 if (config->sample_rate == 0)
8404 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8405 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8406 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8407 if (config->format == AUDIO_FORMAT_DEFAULT)
8408 config->format = AUDIO_FORMAT_PCM_16_BIT;
8409
8410 channels = audio_channel_count_from_out_mask(out->channel_mask);
8411
Varun Balaraje49253e2017-07-06 19:48:56 +05308412 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8413 out->usecase = get_interactive_usecase(adev);
8414 out->config = pcm_config_low_latency;
8415 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308416 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008417 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8418 out->flags);
8419 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008420 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8421 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8422 out->config = pcm_config_mmap_playback;
8423 out->stream.start = out_start;
8424 out->stream.stop = out_stop;
8425 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8426 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308427 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8428 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008429 out->hal_output_suspend_supported =
8430 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8431 out->dynamic_pm_qos_config_supported =
8432 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8433 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008434 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8435 } else {
8436 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8437 //the mixer path will be a string similar to "low-latency-playback resume"
8438 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8439 strlcat(out->pm_qos_mixer_path,
8440 " resume", MAX_MIXER_PATH_LEN);
8441 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8442 out->pm_qos_mixer_path);
8443 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308444 out->config = pcm_config_low_latency;
8445 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8446 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8447 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308448 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8449 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8450 if (out->config.period_size <= 0) {
8451 ALOGE("Invalid configuration period size is not valid");
8452 ret = -EINVAL;
8453 goto error_open;
8454 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008455 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8456 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8457 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008458 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8459 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8460 out->config = pcm_config_haptics_audio;
8461 if (force_haptic_path)
8462 adev->haptics_config = pcm_config_haptics_audio;
8463 else
8464 adev->haptics_config = pcm_config_haptics;
8465
Meng Wangd08ce322020-04-02 08:59:20 +08008466 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008467 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8468
8469 if (force_haptic_path) {
8470 out->config.channels = 1;
8471 adev->haptics_config.channels = 1;
8472 } else
8473 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 -08008474 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008475 ret = audio_extn_auto_hal_open_output_stream(out);
8476 if (ret) {
8477 ALOGE("%s: Failed to open output stream for bus device", __func__);
8478 ret = -EINVAL;
8479 goto error_open;
8480 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308481 } else {
8482 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008483 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8484 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308485 }
8486 out->hal_ip_format = format = out->format;
8487 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8488 out->hal_op_format = pcm_format_to_hal(out->config.format);
8489 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8490 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008491 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308492 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308493 if (out->hal_ip_format != out->hal_op_format) {
8494 uint32_t buffer_size = out->config.period_size *
8495 format_to_bitwidth_table[out->hal_op_format] *
8496 out->config.channels;
8497 out->convert_buffer = calloc(1, buffer_size);
8498 if (out->convert_buffer == NULL){
8499 ALOGE("Allocation failed for convert buffer for size %d",
8500 out->compr_config.fragment_size);
8501 ret = -ENOMEM;
8502 goto error_open;
8503 }
8504 ALOGD("Convert buffer allocated of size %d", buffer_size);
8505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506 }
8507
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008508 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8509 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308510
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008511 /* TODO remove this hardcoding and check why width is zero*/
8512 if (out->bit_width == 0)
8513 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308514 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008515 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008516 &out->device_list, out->flags,
8517 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308518 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308519 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008520 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008521 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8522 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008523 if(adev->primary_output == NULL)
8524 adev->primary_output = out;
8525 else {
8526 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008527 ret = -EEXIST;
8528 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008529 }
8530 }
8531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008532 /* Check if this usecase is already existing */
8533 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008534 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8535 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008536 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008537 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008538 ret = -EEXIST;
8539 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008540 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008542 pthread_mutex_unlock(&adev->lock);
8543
8544 out->stream.common.get_sample_rate = out_get_sample_rate;
8545 out->stream.common.set_sample_rate = out_set_sample_rate;
8546 out->stream.common.get_buffer_size = out_get_buffer_size;
8547 out->stream.common.get_channels = out_get_channels;
8548 out->stream.common.get_format = out_get_format;
8549 out->stream.common.set_format = out_set_format;
8550 out->stream.common.standby = out_standby;
8551 out->stream.common.dump = out_dump;
8552 out->stream.common.set_parameters = out_set_parameters;
8553 out->stream.common.get_parameters = out_get_parameters;
8554 out->stream.common.add_audio_effect = out_add_audio_effect;
8555 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8556 out->stream.get_latency = out_get_latency;
8557 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008558#ifdef NO_AUDIO_OUT
8559 out->stream.write = out_write_for_no_output;
8560#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008561 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008562#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008563 out->stream.get_render_position = out_get_render_position;
8564 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008565 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008566
Haynes Mathew George16081042017-05-31 17:16:49 -07008567 if (out->realtime)
8568 out->af_period_multiplier = af_period_multiplier;
8569 else
8570 out->af_period_multiplier = 1;
8571
Andy Hunga1f48fa2019-07-01 18:14:53 -07008572 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008574 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008575 out->volume_l = PLAYBACK_GAIN_MAX;
8576 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008577 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008578 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008579
8580 config->format = out->stream.common.get_format(&out->stream.common);
8581 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8582 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308583 register_format(out->format, out->supported_formats);
8584 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8585 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008586
Aalique Grahame22e49102018-12-18 14:23:57 -08008587 out->error_log = error_log_create(
8588 ERROR_LOG_ENTRIES,
8589 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8590
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308591 /*
8592 By locking output stream before registering, we allow the callback
8593 to update stream's state only after stream's initial state is set to
8594 adev state.
8595 */
8596 lock_output_stream(out);
8597 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8598 pthread_mutex_lock(&adev->lock);
8599 out->card_status = adev->card_status;
8600 pthread_mutex_unlock(&adev->lock);
8601 pthread_mutex_unlock(&out->lock);
8602
Aalique Grahame22e49102018-12-18 14:23:57 -08008603 stream_app_type_cfg_init(&out->app_type_cfg);
8604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008605 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308606 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008607 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008608
8609 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8610 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8611 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008612 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308613 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008614 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008615 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308616 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8617 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008618 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8619 out->usecase, PCM_PLAYBACK);
8620 hdlr_stream_cfg.flags = out->flags;
8621 hdlr_stream_cfg.type = PCM_PLAYBACK;
8622 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8623 &hdlr_stream_cfg);
8624 if (ret) {
8625 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8626 out->adsp_hdlr_stream_handle = NULL;
8627 }
8628 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308629 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8630 is_direct_passthough, false);
8631 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8632 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008633 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008634 if (ret < 0) {
8635 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8636 out->ip_hdlr_handle = NULL;
8637 }
8638 }
Derek Chenf939fb72018-11-13 13:34:41 -08008639
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008640 ret = io_streams_map_insert(adev, &out->stream.common,
8641 out->handle, AUDIO_PATCH_HANDLE_NONE);
8642 if (ret != 0)
8643 goto error_open;
8644
Derek Chenf939fb72018-11-13 13:34:41 -08008645 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8646 calloc(1, sizeof(streams_output_ctxt_t));
8647 if (out_ctxt == NULL) {
8648 ALOGE("%s fail to allocate output ctxt", __func__);
8649 ret = -ENOMEM;
8650 goto error_open;
8651 }
8652 out_ctxt->output = out;
8653
8654 pthread_mutex_lock(&adev->lock);
8655 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8656 pthread_mutex_unlock(&adev->lock);
8657
Eric Laurent994a6932013-07-17 11:51:42 -07008658 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008659 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008660
8661error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308662 if (out->convert_buffer)
8663 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008664 free(out);
8665 *stream_out = NULL;
8666 ALOGD("%s: exit: ret %d", __func__, ret);
8667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008668}
8669
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308670void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008671 struct audio_stream_out *stream)
8672{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008673 struct stream_out *out = (struct stream_out *)stream;
8674 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008675 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008676
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008677 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308678
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008679 io_streams_map_remove(adev, out->handle);
8680
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308681 // must deregister from sndmonitor first to prevent races
8682 // between the callback and close_stream
8683 audio_extn_snd_mon_unregister_listener(out);
8684
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008685 /* close adsp hdrl session before standby */
8686 if (out->adsp_hdlr_stream_handle) {
8687 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8688 if (ret)
8689 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8690 out->adsp_hdlr_stream_handle = NULL;
8691 }
8692
Manish Dewangan21a850a2017-08-14 12:03:55 +05308693 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008694 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8695 out->ip_hdlr_handle = NULL;
8696 }
8697
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008698 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308699 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008700 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308701 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308702 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008703 if(ret != 0)
8704 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8705 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008706 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008707 out_standby(&stream->common);
8708
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008709 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008710 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008711 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008712 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008713 if (out->compr_config.codec != NULL)
8714 free(out->compr_config.codec);
8715 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008716
Zhou Songbaddf9f2020-11-20 13:57:39 +08008717 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308718
Varun Balaraje49253e2017-07-06 19:48:56 +05308719 if (is_interactive_usecase(out->usecase))
8720 free_interactive_usecase(adev, out->usecase);
8721
Ashish Jain83a6cc22016-06-28 14:34:17 +05308722 if (out->convert_buffer != NULL) {
8723 free(out->convert_buffer);
8724 out->convert_buffer = NULL;
8725 }
8726
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008727 if (adev->voice_tx_output == out)
8728 adev->voice_tx_output = NULL;
8729
Aalique Grahame22e49102018-12-18 14:23:57 -08008730 error_log_destroy(out->error_log);
8731 out->error_log = NULL;
8732
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308733 if (adev->primary_output == out)
8734 adev->primary_output = NULL;
8735
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008736 pthread_cond_destroy(&out->cond);
8737 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008738 pthread_mutex_destroy(&out->pre_lock);
8739 pthread_mutex_destroy(&out->latch_lock);
8740 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008741
8742 pthread_mutex_lock(&adev->lock);
8743 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8744 if (out_ctxt != NULL) {
8745 list_remove(&out_ctxt->list);
8746 free(out_ctxt);
8747 } else {
8748 ALOGW("%s, output stream already closed", __func__);
8749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008750 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008751 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008752 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008753}
8754
8755static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8756{
8757 struct audio_device *adev = (struct audio_device *)dev;
8758 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008759 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008760 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008761 int ret;
8762 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008763 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008764 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008765 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008767 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008768 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008769
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308770 if (!parms)
8771 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308772
Derek Chen6f293672019-04-01 01:40:24 -07008773 /* notify adev and input/output streams on the snd card status */
8774 adev_snd_mon_cb((void *)adev, parms);
8775
Weiyin Jiang24f55292020-12-22 14:35:46 +08008776 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8777 if (ret >= 0) {
8778 list_for_each(node, &adev->active_outputs_list) {
8779 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8780 streams_output_ctxt_t,
8781 list);
8782 out_snd_mon_cb((void *)out_ctxt->output, parms);
8783 }
Derek Chen6f293672019-04-01 01:40:24 -07008784
Weiyin Jiang24f55292020-12-22 14:35:46 +08008785 list_for_each(node, &adev->active_inputs_list) {
8786 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8787 streams_input_ctxt_t,
8788 list);
8789 in_snd_mon_cb((void *)in_ctxt->input, parms);
8790 }
Derek Chen6f293672019-04-01 01:40:24 -07008791 }
8792
Zhou Songd6d71752019-05-21 18:08:51 +08008793 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308794 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8795 if (ret >= 0) {
8796 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008797 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308798 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008799 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308800 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008801 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008802 }
8803 }
8804
8805 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008806 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008807 if (!strncmp(value, "false", 5) &&
8808 audio_extn_a2dp_source_is_suspended()) {
8809 struct audio_usecase *usecase;
8810 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008811 list_for_each(node, &adev->usecase_list) {
8812 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008813 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008814 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008815 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008816 reassign_device_list(&usecase->stream.in->device_list,
8817 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008818 select_devices(adev, usecase->id);
8819 }
Zhou Songd6d71752019-05-21 18:08:51 +08008820 }
8821 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308822 }
8823
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008824 status = voice_set_parameters(adev, parms);
8825 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008826 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008827
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008828 status = platform_set_parameters(adev->platform, parms);
8829 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008830 goto done;
8831
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008832 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8833 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008834 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008835 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8836 adev->bluetooth_nrec = true;
8837 else
8838 adev->bluetooth_nrec = false;
8839 }
8840
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008841 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8842 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008843 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8844 adev->screen_off = false;
8845 else
8846 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008847 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008848 }
8849
Eric Laurent4b084132018-10-19 17:33:43 -07008850 ret = str_parms_get_int(parms, "rotation", &val);
8851 if (ret >= 0) {
8852 bool reverse_speakers = false;
8853 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8854 switch (val) {
8855 // FIXME: note that the code below assumes that the speakers are in the correct placement
8856 // relative to the user when the device is rotated 90deg from its default rotation. This
8857 // assumption is device-specific, not platform-specific like this code.
8858 case 270:
8859 reverse_speakers = true;
8860 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8861 break;
8862 case 0:
8863 case 180:
8864 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8865 break;
8866 case 90:
8867 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8868 break;
8869 default:
8870 ALOGE("%s: unexpected rotation of %d", __func__, val);
8871 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008872 }
Eric Laurent4b084132018-10-19 17:33:43 -07008873 if (status == 0) {
8874 // check and set swap
8875 // - check if orientation changed and speaker active
8876 // - set rotation and cache the rotation value
8877 adev->camera_orientation =
8878 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8879 if (!audio_extn_is_maxx_audio_enabled())
8880 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8881 }
8882 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008883
Mingming Yin514a8bc2014-07-29 15:22:21 -07008884 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8885 if (ret >= 0) {
8886 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8887 adev->bt_wb_speech_enabled = true;
8888 else
8889 adev->bt_wb_speech_enabled = false;
8890 }
8891
Zhou Song12c29502019-03-16 10:37:18 +08008892 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8893 if (ret >= 0) {
8894 val = atoi(value);
8895 adev->swb_speech_mode = val;
8896 }
8897
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008898 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8899 if (ret >= 0) {
8900 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308901 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008902 if (audio_is_output_device(val) &&
8903 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008904 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008905 platform_get_controller_stream_from_params(parms, &controller, &stream);
8906 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8907 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008908 if (ret < 0) {
8909 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308910 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008911 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008912 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308913 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008914 /*
8915 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8916 * Per AudioPolicyManager, USB device is higher priority than WFD.
8917 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8918 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8919 * starting voice call on USB
8920 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008921 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308922 if (ret >= 0)
8923 audio_extn_usb_add_device(device, atoi(value));
8924
Zhou Song6f862822017-11-06 17:27:57 +08008925 if (!audio_extn_usb_is_tunnel_supported()) {
8926 ALOGV("detected USB connect .. disable proxy");
8927 adev->allow_afe_proxy_usage = false;
8928 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008929 }
8930 }
8931
8932 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8933 if (ret >= 0) {
8934 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308935 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008936 /*
8937 * The HDMI / Displayport disconnect handling has been moved to
8938 * audio extension to ensure that its parameters are not
8939 * invalidated prior to updating sysfs of the disconnect event
8940 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8941 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308942 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008943 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308944 if (ret >= 0)
8945 audio_extn_usb_remove_device(device, atoi(value));
8946
Zhou Song6f862822017-11-06 17:27:57 +08008947 if (!audio_extn_usb_is_tunnel_supported()) {
8948 ALOGV("detected USB disconnect .. enable proxy");
8949 adev->allow_afe_proxy_usage = true;
8950 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008951 }
8952 }
8953
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008954 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008955
8956 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008957 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308958 struct audio_usecase *usecase;
8959 struct listnode *node;
8960 list_for_each(node, &adev->usecase_list) {
8961 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008962 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8963 continue;
8964
8965 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308966 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308967 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308968 ALOGD("Switching to speaker and muting the stream before select_devices");
8969 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308970 //force device switch to re configure encoder
8971 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308972 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08008973 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308974 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308975 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08008976 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008977 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08008978 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08008979 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8980 reassign_device_list(&usecase->stream.out->device_list,
8981 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8982 check_a2dp_restore_l(adev, usecase->stream.out, true);
8983 break;
8984 }
8985 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308986 }
8987 }
8988 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008989
8990 //handle vr audio setparam
8991 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8992 value, sizeof(value));
8993 if (ret >= 0) {
8994 ALOGI("Setting vr mode to be %s", value);
8995 if (!strncmp(value, "true", 4)) {
8996 adev->vr_audio_mode_enabled = true;
8997 ALOGI("Setting vr mode to true");
8998 } else if (!strncmp(value, "false", 5)) {
8999 adev->vr_audio_mode_enabled = false;
9000 ALOGI("Setting vr mode to false");
9001 } else {
9002 ALOGI("wrong vr mode set");
9003 }
9004 }
9005
Eric Laurent4b084132018-10-19 17:33:43 -07009006 //FIXME: to be replaced by proper video capture properties API
9007 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9008 if (ret >= 0) {
9009 int camera_facing = CAMERA_FACING_BACK;
9010 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9011 camera_facing = CAMERA_FACING_FRONT;
9012 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9013 camera_facing = CAMERA_FACING_BACK;
9014 else {
9015 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9016 goto done;
9017 }
9018 adev->camera_orientation =
9019 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9020 struct audio_usecase *usecase;
9021 struct listnode *node;
9022 list_for_each(node, &adev->usecase_list) {
9023 usecase = node_to_item(node, struct audio_usecase, list);
9024 struct stream_in *in = usecase->stream.in;
9025 if (usecase->type == PCM_CAPTURE && in != NULL &&
9026 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9027 select_devices(adev, in->usecase);
9028 }
9029 }
9030 }
9031
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309032 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009033done:
9034 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009035 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309036error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009037 ALOGV("%s: exit with code(%d)", __func__, status);
9038 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009039}
9040
9041static char* adev_get_parameters(const struct audio_hw_device *dev,
9042 const char *keys)
9043{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309044 ALOGD("%s:%s", __func__, keys);
9045
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009046 struct audio_device *adev = (struct audio_device *)dev;
9047 struct str_parms *reply = str_parms_create();
9048 struct str_parms *query = str_parms_create_str(keys);
9049 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309050 char value[256] = {0};
9051 int ret = 0;
9052
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009053 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009054 if (reply) {
9055 str_parms_destroy(reply);
9056 }
9057 if (query) {
9058 str_parms_destroy(query);
9059 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009060 ALOGE("adev_get_parameters: failed to create query or reply");
9061 return NULL;
9062 }
9063
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009064 //handle vr audio getparam
9065
9066 ret = str_parms_get_str(query,
9067 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9068 value, sizeof(value));
9069
9070 if (ret >= 0) {
9071 bool vr_audio_enabled = false;
9072 pthread_mutex_lock(&adev->lock);
9073 vr_audio_enabled = adev->vr_audio_mode_enabled;
9074 pthread_mutex_unlock(&adev->lock);
9075
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009076 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009077
9078 if (vr_audio_enabled) {
9079 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9080 "true");
9081 goto exit;
9082 } else {
9083 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9084 "false");
9085 goto exit;
9086 }
9087 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009088
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009089 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009090 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009091 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009092 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009093 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009094 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309095 pthread_mutex_unlock(&adev->lock);
9096
Naresh Tannirud7205b62014-06-20 02:54:48 +05309097exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009098 str = str_parms_to_str(reply);
9099 str_parms_destroy(query);
9100 str_parms_destroy(reply);
9101
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009102 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009103 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009104}
9105
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009106static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009107{
9108 return 0;
9109}
9110
9111static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9112{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009113 int ret;
9114 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009115
9116 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9117
Haynes Mathew George5191a852013-09-11 14:19:36 -07009118 pthread_mutex_lock(&adev->lock);
9119 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009120 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009121 pthread_mutex_unlock(&adev->lock);
9122 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123}
9124
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009125static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9126 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009127{
9128 return -ENOSYS;
9129}
9130
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009131static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9132 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009133{
9134 return -ENOSYS;
9135}
9136
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009137static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9138 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009139{
9140 return -ENOSYS;
9141}
9142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009143static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9144 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009145{
9146 return -ENOSYS;
9147}
9148
9149static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9150{
9151 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009152 struct listnode *node;
9153 struct audio_usecase *usecase = NULL;
9154 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156 pthread_mutex_lock(&adev->lock);
9157 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309158 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9159 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009160 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009161 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309162 adev->current_call_output = adev->primary_output;
9163 voice_start_call(adev);
9164 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009165 (mode == AUDIO_MODE_NORMAL ||
9166 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009167 list_for_each(node, &adev->usecase_list) {
9168 usecase = node_to_item(node, struct audio_usecase, list);
9169 if (usecase->type == VOICE_CALL)
9170 break;
9171 }
9172 if (usecase &&
9173 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9174 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9175 true);
9176 if (ret != 0) {
9177 /* default service interval was successfully updated,
9178 reopen USB backend with new service interval */
9179 check_usecases_codec_backend(adev,
9180 usecase,
9181 usecase->out_snd_device);
9182 }
9183 }
9184
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009185 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009186 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009187 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009188 // restore device for other active usecases after stop call
9189 list_for_each(node, &adev->usecase_list) {
9190 usecase = node_to_item(node, struct audio_usecase, list);
9191 select_devices(adev, usecase->id);
9192 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009194 }
9195 pthread_mutex_unlock(&adev->lock);
9196 return 0;
9197}
9198
9199static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9200{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009201 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009202 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009203
9204 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009205 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009206 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009207
Derek Chend2530072014-11-24 12:39:14 -08009208 if (adev->ext_hw_plugin)
9209 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009210
9211 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009212 pthread_mutex_unlock(&adev->lock);
9213
9214 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009215}
9216
9217static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9218{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009219 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009220 return 0;
9221}
9222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009223static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009224 const struct audio_config *config)
9225{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009226 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009227
Aalique Grahame22e49102018-12-18 14:23:57 -08009228 /* Don't know if USB HIFI in this context so use true to be conservative */
9229 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9230 true /*is_usb_hifi */) != 0)
9231 return 0;
9232
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009233 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9234 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009235}
9236
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009237static bool adev_input_allow_hifi_record(struct audio_device *adev,
9238 audio_devices_t devices,
9239 audio_input_flags_t flags,
9240 audio_source_t source) {
9241 const bool allowed = true;
9242
9243 if (!audio_is_usb_in_device(devices))
9244 return !allowed;
9245
9246 switch (flags) {
9247 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009248 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009249 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9250 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009251 default:
9252 return !allowed;
9253 }
9254
9255 switch (source) {
9256 case AUDIO_SOURCE_DEFAULT:
9257 case AUDIO_SOURCE_MIC:
9258 case AUDIO_SOURCE_UNPROCESSED:
9259 break;
9260 default:
9261 return !allowed;
9262 }
9263
9264 switch (adev->mode) {
9265 case 0:
9266 break;
9267 default:
9268 return !allowed;
9269 }
9270
9271 return allowed;
9272}
9273
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009274static int adev_update_voice_comm_input_stream(struct stream_in *in,
9275 struct audio_config *config)
9276{
9277 bool valid_rate = (config->sample_rate == 8000 ||
9278 config->sample_rate == 16000 ||
9279 config->sample_rate == 32000 ||
9280 config->sample_rate == 48000);
9281 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9282
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009283 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009284 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009285 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9286 in->config = default_pcm_config_voip_copp;
9287 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9288 DEFAULT_VOIP_BUF_DURATION_MS,
9289 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009290 } else {
9291 ALOGW("%s No valid input in voip, use defaults"
9292 "sample rate %u, channel mask 0x%X",
9293 __func__, config->sample_rate, in->channel_mask);
9294 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009295 in->config.rate = config->sample_rate;
9296 in->sample_rate = config->sample_rate;
9297 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009298 //XXX needed for voice_extn_compress_voip_open_input_stream
9299 in->config.rate = config->sample_rate;
9300 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309301 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009302 voice_extn_compress_voip_is_active(in->dev)) &&
9303 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9304 valid_rate && valid_ch) {
9305 voice_extn_compress_voip_open_input_stream(in);
9306 // update rate entries to match config from AF
9307 in->config.rate = config->sample_rate;
9308 in->sample_rate = config->sample_rate;
9309 } else {
9310 ALOGW("%s compress voip not active, use defaults", __func__);
9311 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009312 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009313 return 0;
9314}
9315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009316static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009317 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009318 audio_devices_t devices,
9319 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009320 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309321 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009322 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009323 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009324{
9325 struct audio_device *adev = (struct audio_device *)dev;
9326 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009327 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009328 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009329 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309330 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009331 bool is_usb_dev = audio_is_usb_in_device(devices);
9332 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9333 devices,
9334 flags,
9335 source);
Andy Hung94320602018-10-29 18:31:12 -07009336 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9337 " sample_rate %u, channel_mask %#x, format %#x",
9338 __func__, flags, is_usb_dev, may_use_hifi_record,
9339 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309340
kunleizdff872d2018-08-20 14:40:33 +08009341 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009342 is_usb_dev = false;
9343 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9344 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9345 __func__, devices);
9346 }
9347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009348 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009349
9350 if (!(is_usb_dev && may_use_hifi_record)) {
9351 if (config->sample_rate == 0)
9352 config->sample_rate = 48000;
9353 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9354 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9355 if (config->format == AUDIO_FORMAT_DEFAULT)
9356 config->format = AUDIO_FORMAT_PCM_16_BIT;
9357
9358 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9359
Aalique Grahame22e49102018-12-18 14:23:57 -08009360 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9361 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009362 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009364
Rahul Sharma99770982019-03-06 17:05:26 +05309365 pthread_mutex_lock(&adev->lock);
9366 if (in_get_stream(adev, handle) != NULL) {
9367 ALOGW("%s, input stream already opened", __func__);
9368 ret = -EEXIST;
9369 }
9370 pthread_mutex_unlock(&adev->lock);
9371 if (ret)
9372 return ret;
9373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009374 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009375
9376 if (!in) {
9377 ALOGE("failed to allocate input stream");
9378 return -ENOMEM;
9379 }
9380
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309381 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309382 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9383 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009384 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009385 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009387 in->stream.common.get_sample_rate = in_get_sample_rate;
9388 in->stream.common.set_sample_rate = in_set_sample_rate;
9389 in->stream.common.get_buffer_size = in_get_buffer_size;
9390 in->stream.common.get_channels = in_get_channels;
9391 in->stream.common.get_format = in_get_format;
9392 in->stream.common.set_format = in_set_format;
9393 in->stream.common.standby = in_standby;
9394 in->stream.common.dump = in_dump;
9395 in->stream.common.set_parameters = in_set_parameters;
9396 in->stream.common.get_parameters = in_get_parameters;
9397 in->stream.common.add_audio_effect = in_add_audio_effect;
9398 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9399 in->stream.set_gain = in_set_gain;
9400 in->stream.read = in_read;
9401 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009402 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309403 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009404 in->stream.set_microphone_direction = in_set_microphone_direction;
9405 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009406 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009407
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009408 list_init(&in->device_list);
9409 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009410 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009411 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009412 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009413 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009414 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009415 in->bit_width = 16;
9416 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009417 in->direction = MIC_DIRECTION_UNSPECIFIED;
9418 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009419 list_init(&in->aec_list);
9420 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009421 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009422
Andy Hung94320602018-10-29 18:31:12 -07009423 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009424 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9425 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9426 /* Force channel config requested to mono if incall
9427 record is being requested for only uplink/downlink */
9428 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9429 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9430 ret = -EINVAL;
9431 goto err_open;
9432 }
9433 }
9434
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009435 if (is_usb_dev && may_use_hifi_record) {
9436 /* HiFi record selects an appropriate format, channel, rate combo
9437 depending on sink capabilities*/
9438 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9439 &config->format,
9440 &in->supported_formats[0],
9441 MAX_SUPPORTED_FORMATS,
9442 &config->channel_mask,
9443 &in->supported_channel_masks[0],
9444 MAX_SUPPORTED_CHANNEL_MASKS,
9445 &config->sample_rate,
9446 &in->supported_sample_rates[0],
9447 MAX_SUPPORTED_SAMPLE_RATES);
9448 if (ret != 0) {
9449 ret = -EINVAL;
9450 goto err_open;
9451 }
9452 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009453 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309454 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309455 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9456 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9457 in->config.format = PCM_FORMAT_S32_LE;
9458 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309459 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9460 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9461 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9462 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9463 bool ret_error = false;
9464 in->bit_width = 24;
9465 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9466 from HAL is 24_packed and 8_24
9467 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9468 24_packed return error indicating supported format is 24_packed
9469 *> In case of any other source requesting 24 bit or float return error
9470 indicating format supported is 16 bit only.
9471
9472 on error flinger will retry with supported format passed
9473 */
9474 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9475 (source != AUDIO_SOURCE_CAMCORDER)) {
9476 config->format = AUDIO_FORMAT_PCM_16_BIT;
9477 if (config->sample_rate > 48000)
9478 config->sample_rate = 48000;
9479 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009480 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9481 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309482 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9483 ret_error = true;
9484 }
9485
9486 if (ret_error) {
9487 ret = -EINVAL;
9488 goto err_open;
9489 }
9490 }
9491
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009492 in->channel_mask = config->channel_mask;
9493 in->format = config->format;
9494
9495 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309496
Huicheng Liu1404ba12020-09-11 01:03:25 -04009497 /* validate bus device address */
9498 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9499 /* extract car audio stream index */
9500 in->car_audio_stream =
9501 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9502 if (in->car_audio_stream < 0) {
9503 ALOGE("%s: invalid car audio stream %x",
9504 __func__, in->car_audio_stream);
9505 ret = -EINVAL;
9506 goto err_open;
9507 }
9508 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
9509 }
9510
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309511 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9512 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9513 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9514 else {
9515 ret = -EINVAL;
9516 goto err_open;
9517 }
9518 }
9519
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009520 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309521 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9522 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009523 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9524 is_low_latency = true;
9525#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309526 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9527 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9528 else
9529 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009530#endif
9531 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009532 if (!in->realtime) {
9533 in->config = pcm_config_audio_capture;
9534 frame_size = audio_stream_in_frame_size(&in->stream);
9535 buffer_size = get_input_buffer_size(config->sample_rate,
9536 config->format,
9537 channel_count,
9538 is_low_latency);
9539 in->config.period_size = buffer_size / frame_size;
9540 in->config.rate = config->sample_rate;
9541 in->af_period_multiplier = 1;
9542 } else {
9543 // period size is left untouched for rt mode playback
9544 in->config = pcm_config_audio_capture_rt;
9545 in->af_period_multiplier = af_period_multiplier;
9546 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009547 }
9548
9549 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9550 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9551 in->realtime = 0;
9552 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9553 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009554 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009555 in->stream.start = in_start;
9556 in->stream.stop = in_stop;
9557 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9558 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009559 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009560 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009561 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9562 in->config = pcm_config_audio_capture;
9563 frame_size = audio_stream_in_frame_size(&in->stream);
9564 buffer_size = get_input_buffer_size(config->sample_rate,
9565 config->format,
9566 channel_count,
9567 false /*is_low_latency*/);
9568 in->config.period_size = buffer_size / frame_size;
9569 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009570 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009571 switch (config->format) {
9572 case AUDIO_FORMAT_PCM_32_BIT:
9573 in->bit_width = 32;
9574 break;
9575 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9576 case AUDIO_FORMAT_PCM_8_24_BIT:
9577 in->bit_width = 24;
9578 break;
9579 default:
9580 in->bit_width = 16;
9581 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009582 } else if (is_single_device_type_equal(&in->device_list,
9583 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9584 is_single_device_type_equal(&in->device_list,
9585 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009586 if (config->sample_rate == 0)
9587 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9588 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9589 config->sample_rate != 8000) {
9590 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9591 ret = -EINVAL;
9592 goto err_open;
9593 }
9594 if (config->format == AUDIO_FORMAT_DEFAULT)
9595 config->format = AUDIO_FORMAT_PCM_16_BIT;
9596 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9597 config->format = AUDIO_FORMAT_PCM_16_BIT;
9598 ret = -EINVAL;
9599 goto err_open;
9600 }
9601
9602 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009603 if (adev->ha_proxy_enable &&
9604 is_single_device_type_equal(&in->device_list,
9605 AUDIO_DEVICE_IN_TELEPHONY_RX))
9606 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009607 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009608 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009609 in->af_period_multiplier = 1;
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309610 } else if (in->realtime) {
9611 in->config = pcm_config_audio_capture_rt;
9612 in->config.format = pcm_format_from_audio_format(config->format);
9613 in->af_period_multiplier = af_period_multiplier;
Aalique Grahame22e49102018-12-18 14:23:57 -08009614 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309615 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009616 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9617 (config->sample_rate == 8000 ||
9618 config->sample_rate == 16000 ||
9619 config->sample_rate == 32000 ||
9620 config->sample_rate == 48000) &&
9621 channel_count == 1) {
9622 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9623 in->config = pcm_config_audio_capture;
9624 frame_size = audio_stream_in_frame_size(&in->stream);
9625 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9626 config->sample_rate,
9627 config->format,
9628 channel_count, false /*is_low_latency*/);
9629 in->config.period_size = buffer_size / frame_size;
9630 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9631 in->config.rate = config->sample_rate;
9632 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009633 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309634 int ret_val;
9635 pthread_mutex_lock(&adev->lock);
9636 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9637 in, config, &channel_mask_updated);
9638 pthread_mutex_unlock(&adev->lock);
9639
9640 if (!ret_val) {
9641 if (channel_mask_updated == true) {
9642 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9643 __func__, config->channel_mask);
9644 ret = -EINVAL;
9645 goto err_open;
9646 }
9647 ALOGD("%s: created multi-channel session succesfully",__func__);
9648 } else if (audio_extn_compr_cap_enabled() &&
9649 audio_extn_compr_cap_format_supported(config->format) &&
9650 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9651 audio_extn_compr_cap_init(in);
9652 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309653 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309654 if (ret)
9655 goto err_open;
9656 } else {
9657 in->config = pcm_config_audio_capture;
9658 in->config.rate = config->sample_rate;
9659 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309660 in->format = config->format;
9661 frame_size = audio_stream_in_frame_size(&in->stream);
9662 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009663 config->format,
9664 channel_count,
9665 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009666 /* prevent division-by-zero */
9667 if (frame_size == 0) {
9668 ALOGE("%s: Error frame_size==0", __func__);
9669 ret = -EINVAL;
9670 goto err_open;
9671 }
9672
Revathi Uddarajud2634032017-12-07 14:42:34 +05309673 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009674 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009675
Revathi Uddarajud2634032017-12-07 14:42:34 +05309676 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9677 /* optionally use VOIP usecase depending on config(s) */
9678 ret = adev_update_voice_comm_input_stream(in, config);
9679 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009680
Revathi Uddarajud2634032017-12-07 14:42:34 +05309681 if (ret) {
9682 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9683 goto err_open;
9684 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009685 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309686
9687 /* assign concurrent capture usecase if record has to caried out from
9688 * actual hardware input source */
9689 if (audio_extn_is_concurrent_capture_enabled() &&
9690 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309691 /* Acquire lock to avoid two concurrent use cases initialized to
9692 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009693
Samyak Jainc37062f2019-04-25 18:41:06 +05309694 if (in->usecase == USECASE_AUDIO_RECORD) {
9695 pthread_mutex_lock(&adev->lock);
9696 if (!(adev->pcm_record_uc_state)) {
9697 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9698 adev->pcm_record_uc_state = 1;
9699 pthread_mutex_unlock(&adev->lock);
9700 } else {
9701 pthread_mutex_unlock(&adev->lock);
9702 /* Assign compress record use case for second record */
9703 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9704 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9705 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9706 if (audio_extn_cin_applicable_stream(in)) {
9707 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309708 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309709 if (ret)
9710 goto err_open;
9711 }
9712 }
9713 }
kunleiz28c73e72019-03-27 17:24:04 +08009714 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009715 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9716 ret = audio_extn_auto_hal_open_input_stream(in);
9717 if (ret) {
9718 ALOGE("%s: Failed to open input stream for bus device", __func__);
9719 ret = -EINVAL;
9720 goto err_open;
9721 }
9722 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009723 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309724 if (audio_extn_ssr_get_stream() != in)
9725 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009726
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009727 in->sample_rate = in->config.rate;
9728
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309729 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9730 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009731 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009732 in->sample_rate, in->bit_width,
9733 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309734 register_format(in->format, in->supported_formats);
9735 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9736 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309737
Aalique Grahame22e49102018-12-18 14:23:57 -08009738 in->error_log = error_log_create(
9739 ERROR_LOG_ENTRIES,
9740 1000000000 /* aggregate consecutive identical errors within one second */);
9741
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009742 /* This stream could be for sound trigger lab,
9743 get sound trigger pcm if present */
9744 audio_extn_sound_trigger_check_and_get_session(in);
9745
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309746 lock_input_stream(in);
9747 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9748 pthread_mutex_lock(&adev->lock);
9749 in->card_status = adev->card_status;
9750 pthread_mutex_unlock(&adev->lock);
9751 pthread_mutex_unlock(&in->lock);
9752
Aalique Grahame22e49102018-12-18 14:23:57 -08009753 stream_app_type_cfg_init(&in->app_type_cfg);
9754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009755 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009756
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009757 ret = io_streams_map_insert(adev, &in->stream.common,
9758 handle, AUDIO_PATCH_HANDLE_NONE);
9759 if (ret != 0)
9760 goto err_open;
9761
Derek Chenf939fb72018-11-13 13:34:41 -08009762 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9763 calloc(1, sizeof(streams_input_ctxt_t));
9764 if (in_ctxt == NULL) {
9765 ALOGE("%s fail to allocate input ctxt", __func__);
9766 ret = -ENOMEM;
9767 goto err_open;
9768 }
9769 in_ctxt->input = in;
9770
9771 pthread_mutex_lock(&adev->lock);
9772 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9773 pthread_mutex_unlock(&adev->lock);
9774
Eric Laurent994a6932013-07-17 11:51:42 -07009775 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009776 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009777
9778err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309779 if (in->usecase == USECASE_AUDIO_RECORD) {
9780 pthread_mutex_lock(&adev->lock);
9781 adev->pcm_record_uc_state = 0;
9782 pthread_mutex_unlock(&adev->lock);
9783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009784 free(in);
9785 *stream_in = NULL;
9786 return ret;
9787}
9788
9789static void adev_close_input_stream(struct audio_hw_device *dev,
9790 struct audio_stream_in *stream)
9791{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009792 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009793 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009794 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309795
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309796 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009797
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009798 if (in == NULL) {
9799 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9800 return;
9801 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009802 io_streams_map_remove(adev, in->capture_handle);
9803
kunleiz70e57612018-12-28 17:50:23 +08009804 /* must deregister from sndmonitor first to prevent races
9805 * between the callback and close_stream
9806 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309807 audio_extn_snd_mon_unregister_listener(stream);
9808
kunleiz70e57612018-12-28 17:50:23 +08009809 /* Disable echo reference if there are no active input, hfp call
9810 * and sound trigger while closing input stream
9811 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009812 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009813 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009814 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9815 struct listnode out_devices;
9816 list_init(&out_devices);
9817 platform_set_echo_reference(adev, false, &out_devices);
9818 } else
kunleiz70e57612018-12-28 17:50:23 +08009819 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309820
Weiyin Jiang2995f662019-04-17 14:25:12 +08009821 error_log_destroy(in->error_log);
9822 in->error_log = NULL;
9823
Pallavid7c7a272018-01-16 11:22:55 +05309824
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009825 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309826 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009827 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309828 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009829 if (ret != 0)
9830 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9831 __func__, ret);
9832 } else
9833 in_standby(&stream->common);
9834
Weiyin Jiang280ea742020-09-08 20:28:22 +08009835 pthread_mutex_destroy(&in->lock);
9836 pthread_mutex_destroy(&in->pre_lock);
9837
Revathi Uddarajud2634032017-12-07 14:42:34 +05309838 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309839 if (in->usecase == USECASE_AUDIO_RECORD) {
9840 adev->pcm_record_uc_state = 0;
9841 }
9842
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009843 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9844 adev->enable_voicerx = false;
9845 }
9846
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009847 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009848 audio_extn_ssr_deinit();
9849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009850
Garmond Leunge2433c32017-09-28 21:51:22 -07009851 if (audio_extn_ffv_get_stream() == in) {
9852 audio_extn_ffv_stream_deinit();
9853 }
9854
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309855 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009856 audio_extn_compr_cap_format_supported(in->config.format))
9857 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309858
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309859 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309860 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009861
Mingming Yinfd7607b2016-01-22 12:48:44 -08009862 if (in->is_st_session) {
9863 ALOGV("%s: sound trigger pcm stop lab", __func__);
9864 audio_extn_sound_trigger_stop_lab(in);
9865 }
Derek Chenf939fb72018-11-13 13:34:41 -08009866 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9867 if (in_ctxt != NULL) {
9868 list_remove(&in_ctxt->list);
9869 free(in_ctxt);
9870 } else {
9871 ALOGW("%s, input stream already closed", __func__);
9872 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009873 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309874 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009875 return;
9876}
9877
Aalique Grahame22e49102018-12-18 14:23:57 -08009878/* verifies input and output devices and their capabilities.
9879 *
9880 * This verification is required when enabling extended bit-depth or
9881 * sampling rates, as not all qcom products support it.
9882 *
9883 * Suitable for calling only on initialization such as adev_open().
9884 * It fills the audio_device use_case_table[] array.
9885 *
9886 * Has a side-effect that it needs to configure audio routing / devices
9887 * in order to power up the devices and read the device parameters.
9888 * It does not acquire any hw device lock. Should restore the devices
9889 * back to "normal state" upon completion.
9890 */
9891static int adev_verify_devices(struct audio_device *adev)
9892{
9893 /* enumeration is a bit difficult because one really wants to pull
9894 * the use_case, device id, etc from the hidden pcm_device_table[].
9895 * In this case there are the following use cases and device ids.
9896 *
9897 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9898 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9899 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9900 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9901 * [USECASE_AUDIO_RECORD] = {0, 0},
9902 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9903 * [USECASE_VOICE_CALL] = {2, 2},
9904 *
9905 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9906 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9907 */
9908
9909 /* should be the usecases enabled in adev_open_input_stream() */
9910 static const int test_in_usecases[] = {
9911 USECASE_AUDIO_RECORD,
9912 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9913 };
9914 /* should be the usecases enabled in adev_open_output_stream()*/
9915 static const int test_out_usecases[] = {
9916 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9917 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9918 };
9919 static const usecase_type_t usecase_type_by_dir[] = {
9920 PCM_PLAYBACK,
9921 PCM_CAPTURE,
9922 };
9923 static const unsigned flags_by_dir[] = {
9924 PCM_OUT,
9925 PCM_IN,
9926 };
9927
9928 size_t i;
9929 unsigned dir;
9930 const unsigned card_id = adev->snd_card;
9931
9932 for (dir = 0; dir < 2; ++dir) {
9933 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9934 const unsigned flags_dir = flags_by_dir[dir];
9935 const size_t testsize =
9936 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9937 const int *testcases =
9938 dir ? test_in_usecases : test_out_usecases;
9939 const audio_devices_t audio_device =
9940 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9941
9942 for (i = 0; i < testsize; ++i) {
9943 const audio_usecase_t audio_usecase = testcases[i];
9944 int device_id;
9945 struct pcm_params **pparams;
9946 struct stream_out out;
9947 struct stream_in in;
9948 struct audio_usecase uc_info;
9949 int retval;
9950
9951 pparams = &adev->use_case_table[audio_usecase];
9952 pcm_params_free(*pparams); /* can accept null input */
9953 *pparams = NULL;
9954
9955 /* find the device ID for the use case (signed, for error) */
9956 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9957 if (device_id < 0)
9958 continue;
9959
9960 /* prepare structures for device probing */
9961 memset(&uc_info, 0, sizeof(uc_info));
9962 uc_info.id = audio_usecase;
9963 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009964 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009965 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009966 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009967 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009968 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009969 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9970 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009971 }
9972 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009973 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009974 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009975 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009976 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009977 uc_info.in_snd_device = SND_DEVICE_NONE;
9978 uc_info.out_snd_device = SND_DEVICE_NONE;
9979 list_add_tail(&adev->usecase_list, &uc_info.list);
9980
9981 /* select device - similar to start_(in/out)put_stream() */
9982 retval = select_devices(adev, audio_usecase);
9983 if (retval >= 0) {
9984 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9985#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009986 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009987 if (*pparams) {
9988 ALOGV("%s: (%s) card %d device %d", __func__,
9989 dir ? "input" : "output", card_id, device_id);
9990 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9991 } else {
9992 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9993 }
9994#endif
9995 }
9996
9997 /* deselect device - similar to stop_(in/out)put_stream() */
9998 /* 1. Get and set stream specific mixer controls */
9999 retval = disable_audio_route(adev, &uc_info);
10000 /* 2. Disable the rx device */
10001 retval = disable_snd_device(adev,
10002 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10003 list_remove(&uc_info.list);
10004 }
10005 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010006 return 0;
10007}
10008
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010009int update_patch(unsigned int num_sources,
10010 const struct audio_port_config *sources,
10011 unsigned int num_sinks,
10012 const struct audio_port_config *sinks,
10013 audio_patch_handle_t handle,
10014 struct audio_patch_info *p_info,
10015 patch_type_t patch_type, bool new_patch)
10016{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010017 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010018
10019 if (p_info == NULL) {
10020 ALOGE("%s: Invalid patch pointer", __func__);
10021 return -EINVAL;
10022 }
10023
10024 if (new_patch) {
10025 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10026 if (p_info->patch == NULL) {
10027 ALOGE("%s: Could not allocate patch", __func__);
10028 return -ENOMEM;
10029 }
10030 }
10031
10032 p_info->patch->id = handle;
10033 p_info->patch->num_sources = num_sources;
10034 p_info->patch->num_sinks = num_sinks;
10035
10036 for (int i = 0; i < num_sources; i++)
10037 p_info->patch->sources[i] = sources[i];
10038 for (int i = 0; i < num_sinks; i++)
10039 p_info->patch->sinks[i] = sinks[i];
10040
10041 p_info->patch_type = patch_type;
10042 return 0;
10043}
10044
10045audio_patch_handle_t generate_patch_handle()
10046{
10047 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10048 if (++patch_handle < 0)
10049 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10050 return patch_handle;
10051}
10052
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010053int adev_create_audio_patch(struct audio_hw_device *dev,
10054 unsigned int num_sources,
10055 const struct audio_port_config *sources,
10056 unsigned int num_sinks,
10057 const struct audio_port_config *sinks,
10058 audio_patch_handle_t *handle)
10059{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060 int ret = 0;
10061 struct audio_device *adev = (struct audio_device *)dev;
10062 struct audio_patch_info *p_info = NULL;
10063 patch_type_t patch_type = PATCH_NONE;
10064 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10065 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10066 struct audio_stream_info *s_info = NULL;
10067 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010068 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010069 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10070 bool new_patch = false;
10071 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010072
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010073 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10074 num_sources, num_sinks, *handle);
10075
10076 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10077 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10078 ALOGE("%s: Invalid patch arguments", __func__);
10079 ret = -EINVAL;
10080 goto done;
10081 }
10082
10083 if (num_sources > 1) {
10084 ALOGE("%s: Multiple sources are not supported", __func__);
10085 ret = -EINVAL;
10086 goto done;
10087 }
10088
10089 if (sources == NULL || sinks == NULL) {
10090 ALOGE("%s: Invalid sources or sinks port config", __func__);
10091 ret = -EINVAL;
10092 goto done;
10093 }
10094
10095 ALOGV("%s: source role %d, source type %d", __func__,
10096 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010097 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010098
10099 // Populate source/sink information and fetch stream info
10100 switch (sources[0].type) {
10101 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10102 device_type = sources[0].ext.device.type;
10103 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010104 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10106 patch_type = PATCH_CAPTURE;
10107 io_handle = sinks[0].ext.mix.handle;
10108 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010109 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010110 __func__, device_type, io_handle);
10111 } else {
10112 // Device to device patch is not implemented.
10113 // This space will need changes if audio HAL
10114 // handles device to device patches in the future.
10115 patch_type = PATCH_DEVICE_LOOPBACK;
10116 }
10117 break;
10118 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10119 io_handle = sources[0].ext.mix.handle;
10120 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010121 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010122 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010123 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010124 }
10125 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010126 ALOGD("%s: Playback patch from mix handle %d to device %x",
10127 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128 break;
10129 case AUDIO_PORT_TYPE_SESSION:
10130 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010131 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10132 ret = -EINVAL;
10133 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010134 }
10135
10136 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010138 // Generate patch info and update patch
10139 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010140 *handle = generate_patch_handle();
10141 p_info = (struct audio_patch_info *)
10142 calloc(1, sizeof(struct audio_patch_info));
10143 if (p_info == NULL) {
10144 ALOGE("%s: Failed to allocate memory", __func__);
10145 pthread_mutex_unlock(&adev->lock);
10146 ret = -ENOMEM;
10147 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010148 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010149 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010150 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010151 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 if (p_info == NULL) {
10153 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10154 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010155 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010156 ret = -EINVAL;
10157 goto done;
10158 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010159 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010160 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010161 *handle, p_info, patch_type, new_patch);
10162
10163 // Fetch stream info of associated mix for playback or capture patches
10164 if (p_info->patch_type == PATCH_PLAYBACK ||
10165 p_info->patch_type == PATCH_CAPTURE) {
10166 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10167 if (s_info == NULL) {
10168 ALOGE("%s: Failed to obtain stream info", __func__);
10169 if (new_patch)
10170 free(p_info);
10171 pthread_mutex_unlock(&adev->lock);
10172 ret = -EINVAL;
10173 goto done;
10174 }
10175 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10176 s_info->patch_handle = *handle;
10177 stream = s_info->stream;
10178 }
10179 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010180
10181 // Update routing for stream
10182 if (stream != NULL) {
10183 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010184 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010185 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010186 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010187 if (ret < 0) {
10188 pthread_mutex_lock(&adev->lock);
10189 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10190 if (new_patch)
10191 free(p_info);
10192 pthread_mutex_unlock(&adev->lock);
10193 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10194 goto done;
10195 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010196 }
10197
10198 // Add new patch to patch map
10199 if (!ret && new_patch) {
10200 pthread_mutex_lock(&adev->lock);
10201 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010202 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010203 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010204 }
10205
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010206done:
10207 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010208 num_sources,
10209 sources,
10210 num_sinks,
10211 sinks,
10212 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010213 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010214 num_sources,
10215 sources,
10216 num_sinks,
10217 sinks,
10218 handle);
10219 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010220}
10221
10222int adev_release_audio_patch(struct audio_hw_device *dev,
10223 audio_patch_handle_t handle)
10224{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010225 struct audio_device *adev = (struct audio_device *) dev;
10226 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010227 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010228 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010229
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010230 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10231 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10232 ret = -EINVAL;
10233 goto done;
10234 }
10235
10236 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010237 pthread_mutex_lock(&adev->lock);
10238 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010239 if (p_info == NULL) {
10240 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010241 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010242 ret = -EINVAL;
10243 goto done;
10244 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010245 struct audio_patch *patch = p_info->patch;
10246 if (patch == NULL) {
10247 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010248 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010249 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010250 goto done;
10251 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010252 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10253 switch (patch->sources[0].type) {
10254 case AUDIO_PORT_TYPE_MIX:
10255 io_handle = patch->sources[0].ext.mix.handle;
10256 break;
10257 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010258 if (p_info->patch_type == PATCH_CAPTURE)
10259 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010260 break;
10261 case AUDIO_PORT_TYPE_SESSION:
10262 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010263 pthread_mutex_unlock(&adev->lock);
10264 ret = -EINVAL;
10265 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010266 }
10267
10268 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010269 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010270 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010271 if (patch_type == PATCH_PLAYBACK ||
10272 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010273 struct audio_stream_info *s_info =
10274 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10275 if (s_info == NULL) {
10276 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10277 pthread_mutex_unlock(&adev->lock);
10278 goto done;
10279 }
10280 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10281 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010282 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010283 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010284
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010285 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010286 struct listnode devices;
10287 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010288 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010289 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010290 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010291 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010292 }
10293
10294 if (ret < 0)
10295 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10296
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010297done:
10298 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10299 audio_extn_auto_hal_release_audio_patch(dev, handle);
10300
10301 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010302 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010303}
10304
10305int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10306{
Derek Chenf13dd492018-11-13 14:53:51 -080010307 int ret = 0;
10308
10309 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10310 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10311 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010312}
10313
10314int adev_set_audio_port_config(struct audio_hw_device *dev,
10315 const struct audio_port_config *config)
10316{
Derek Chenf13dd492018-11-13 14:53:51 -080010317 int ret = 0;
10318
10319 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10320 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10321 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010322}
10323
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010324static int adev_dump(const audio_hw_device_t *device __unused,
10325 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010326{
10327 return 0;
10328}
10329
10330static int adev_close(hw_device_t *device)
10331{
Aalique Grahame22e49102018-12-18 14:23:57 -080010332 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010333 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010334
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010335 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010336 return 0;
10337
10338 pthread_mutex_lock(&adev_init_lock);
10339
10340 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010341 if (audio_extn_spkr_prot_is_enabled())
10342 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010343 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010344 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010345 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010346 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010347 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010348 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010349 audio_extn_utils_release_streams_cfg_lists(
10350 &adev->streams_output_cfg_list,
10351 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010352 if (audio_extn_qap_is_enabled())
10353 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010354 if (audio_extn_qaf_is_enabled())
10355 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010356 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010357 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010358 free(adev->snd_dev_ref_cnt);
10359 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010360 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10361 pcm_params_free(adev->use_case_table[i]);
10362 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010363 if (adev->adm_deinit)
10364 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010365 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010366 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010367 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010368 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010369 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010370 if (adev->device_cfg_params) {
10371 free(adev->device_cfg_params);
10372 adev->device_cfg_params = NULL;
10373 }
Derek Chend2530072014-11-24 12:39:14 -080010374 if(adev->ext_hw_plugin)
10375 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010376 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010377 free_map(adev->patch_map);
10378 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010379 free(device);
10380 adev = NULL;
10381 }
10382 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010383 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010384 return 0;
10385}
10386
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010387/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10388 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10389 * just that it _might_ work.
10390 */
10391static int period_size_is_plausible_for_low_latency(int period_size)
10392{
10393 switch (period_size) {
10394 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010395 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010396 case 240:
10397 case 320:
10398 case 480:
10399 return 1;
10400 default:
10401 return 0;
10402 }
10403}
10404
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010405static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10406{
10407 bool is_snd_card_status = false;
10408 bool is_ext_device_status = false;
10409 char value[32];
10410 int card = -1;
10411 card_status_t status;
10412
10413 if (cookie != adev || !parms)
10414 return;
10415
10416 if (!parse_snd_card_status(parms, &card, &status)) {
10417 is_snd_card_status = true;
10418 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10419 is_ext_device_status = true;
10420 } else {
10421 // not a valid event
10422 return;
10423 }
10424
10425 pthread_mutex_lock(&adev->lock);
10426 if (card == adev->snd_card || is_ext_device_status) {
10427 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010428 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010429 adev->card_status = status;
10430 platform_snd_card_update(adev->platform, status);
10431 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010432 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010433 if (status == CARD_STATUS_OFFLINE)
10434 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010435 } else if (is_ext_device_status) {
10436 platform_set_parameters(adev->platform, parms);
10437 }
10438 }
10439 pthread_mutex_unlock(&adev->lock);
10440 return;
10441}
10442
Weiyin Jiang280ea742020-09-08 20:28:22 +080010443/* adev lock held */
10444int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010445{
10446 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010447 struct audio_usecase *usecase;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010448 float left_p;
10449 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010450 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010451 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010452
10453 uc_info = get_usecase_from_list(adev, out->usecase);
10454 if (uc_info == NULL) {
10455 ALOGE("%s: Could not find the usecase (%d) in the list",
10456 __func__, out->usecase);
10457 return -EINVAL;
10458 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010459 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010460
Zhou Songbaddf9f2020-11-20 13:57:39 +080010461 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10462 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010463
10464 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010465 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010466 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010467 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010468 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010469 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10470 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010471
10472 if (is_offload_usecase(out->usecase)) {
10473 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010474 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010475 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10476 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10477 } else {
10478 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010479 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010480 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010482 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010483 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010484 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010485 // mute stream and switch to speaker if suspended
10486 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010487 assign_devices(&devices, &out->device_list);
10488 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010489 list_for_each(node, &adev->usecase_list) {
10490 usecase = node_to_item(node, struct audio_usecase, list);
10491 if ((usecase != uc_info) &&
10492 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10493 usecase->out_snd_device)) {
10494 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10495 break;
10496 }
10497 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010498 left_p = out->volume_l;
10499 right_p = out->volume_r;
10500 out->a2dp_muted = true;
10501 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010502 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10503 compress_pause(out->compr);
10504 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010505 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10506 out_set_voip_volume(&out->stream, (float)0, (float)0);
10507 } else {
10508 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10509 /* wait for stale pcm drained before switching to speaker */
10510 uint32_t latency =
10511 (out->config.period_count * out->config.period_size * 1000) /
10512 (out->config.rate);
10513 usleep(latency * 1000);
10514 }
10515 select_devices(adev, out->usecase);
Zhou Song407e5aa2020-12-27 19:13:04 +080010516 ALOGD("%s: switched to device:%s and mute stream",
10517 __func__, platform_get_snd_device_name(uc_info->out_snd_device));
Zhou Songbaddf9f2020-11-20 13:57:39 +080010518 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010519 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10520 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010521 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010522 assign_devices(&out->device_list, &devices);
10523 out->volume_l = left_p;
10524 out->volume_r = right_p;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010525 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010526 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010527 }
10528 ALOGV("%s: exit", __func__);
10529 return 0;
10530}
10531
Haynes Mathew George01156f92018-04-13 15:29:54 -070010532void adev_on_battery_status_changed(bool charging)
10533{
10534 pthread_mutex_lock(&adev->lock);
10535 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10536 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010537 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010538 pthread_mutex_unlock(&adev->lock);
10539}
10540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010541static int adev_open(const hw_module_t *module, const char *name,
10542 hw_device_t **device)
10543{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010544 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010545 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010546 char mixer_ctl_name[128] = {0};
10547 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010548
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010549 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010550 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10551
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010552 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010553 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010554 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010555 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010556 ALOGD("%s: returning existing instance of adev", __func__);
10557 ALOGD("%s: exit", __func__);
10558 pthread_mutex_unlock(&adev_init_lock);
10559 return 0;
10560 }
10561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010562 adev = calloc(1, sizeof(struct audio_device));
10563
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010564 if (!adev) {
10565 pthread_mutex_unlock(&adev_init_lock);
10566 return -ENOMEM;
10567 }
10568
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010569 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10570
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010571 // register audio ext hidl at the earliest
10572 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010573#ifdef DYNAMIC_LOG_ENABLED
10574 register_for_dynamic_logging("hal");
10575#endif
10576
Derek Chenf939fb72018-11-13 13:34:41 -080010577 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010578 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010579 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10580 maj_version = atoi(value);
10581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010582 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010583 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010584 adev->device.common.module = (struct hw_module_t *)module;
10585 adev->device.common.close = adev_close;
10586
10587 adev->device.init_check = adev_init_check;
10588 adev->device.set_voice_volume = adev_set_voice_volume;
10589 adev->device.set_master_volume = adev_set_master_volume;
10590 adev->device.get_master_volume = adev_get_master_volume;
10591 adev->device.set_master_mute = adev_set_master_mute;
10592 adev->device.get_master_mute = adev_get_master_mute;
10593 adev->device.set_mode = adev_set_mode;
10594 adev->device.set_mic_mute = adev_set_mic_mute;
10595 adev->device.get_mic_mute = adev_get_mic_mute;
10596 adev->device.set_parameters = adev_set_parameters;
10597 adev->device.get_parameters = adev_get_parameters;
10598 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10599 adev->device.open_output_stream = adev_open_output_stream;
10600 adev->device.close_output_stream = adev_close_output_stream;
10601 adev->device.open_input_stream = adev_open_input_stream;
10602 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010603 adev->device.create_audio_patch = adev_create_audio_patch;
10604 adev->device.release_audio_patch = adev_release_audio_patch;
10605 adev->device.get_audio_port = adev_get_audio_port;
10606 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010607 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010608 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010609
10610 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010611 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010612 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010613 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010614 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010615 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010616 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010617 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010618 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010619 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010620 /* Init audio and voice feature */
10621 audio_extn_feature_init();
10622 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010623 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010624 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010625 list_init(&adev->active_inputs_list);
10626 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010627 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010628 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10629 audio_extn_utils_hash_eq);
10630 if (!adev->io_streams_map) {
10631 ALOGE("%s: Could not create io streams map", __func__);
10632 ret = -ENOMEM;
10633 goto adev_open_err;
10634 }
10635 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10636 audio_extn_utils_hash_eq);
10637 if (!adev->patch_map) {
10638 ALOGE("%s: Could not create audio patch map", __func__);
10639 ret = -ENOMEM;
10640 goto adev_open_err;
10641 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010642 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010643 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010644 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010645 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010646 adev->perf_lock_opts[0] = 0x101;
10647 adev->perf_lock_opts[1] = 0x20E;
10648 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010649 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010650 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010651 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010652 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010653 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010654
Zhou Song68ebc352019-12-05 17:11:15 +080010655 audio_extn_perf_lock_init();
10656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010657 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010658 adev->platform = platform_init(adev);
10659 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010660 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010661 ret = -EINVAL;
10662 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010663 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010664
Aalique Grahame22e49102018-12-18 14:23:57 -080010665 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010666 if (audio_extn_qap_is_enabled()) {
10667 ret = audio_extn_qap_init(adev);
10668 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010669 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010670 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010671 }
10672 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10673 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10674 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010675
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010676 if (audio_extn_qaf_is_enabled()) {
10677 ret = audio_extn_qaf_init(adev);
10678 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010679 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010680 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010681 }
10682
10683 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10684 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10685 }
10686
Derek Chenae7b0342019-02-08 15:17:04 -080010687 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010688 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10689
Eric Laurentc4aef752013-09-12 17:45:53 -070010690 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10691 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10692 if (adev->visualizer_lib == NULL) {
10693 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10694 } else {
10695 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10696 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010697 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010698 "visualizer_hal_start_output");
10699 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010700 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010701 "visualizer_hal_stop_output");
10702 }
10703 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010704 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010705 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010706 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010707 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010708 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010709 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010710
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010711 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10712 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10713 if (adev->offload_effects_lib == NULL) {
10714 ALOGE("%s: DLOPEN failed for %s", __func__,
10715 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10716 } else {
10717 ALOGV("%s: DLOPEN successful for %s", __func__,
10718 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10719 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010720 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010721 "offload_effects_bundle_hal_start_output");
10722 adev->offload_effects_stop_output =
10723 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10724 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010725 adev->offload_effects_set_hpx_state =
10726 (int (*)(bool))dlsym(adev->offload_effects_lib,
10727 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010728 adev->offload_effects_get_parameters =
10729 (void (*)(struct str_parms *, struct str_parms *))
10730 dlsym(adev->offload_effects_lib,
10731 "offload_effects_bundle_get_parameters");
10732 adev->offload_effects_set_parameters =
10733 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10734 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010735 }
10736 }
10737
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010738 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10739 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10740 if (adev->adm_lib == NULL) {
10741 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10742 } else {
10743 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10744 adev->adm_init = (adm_init_t)
10745 dlsym(adev->adm_lib, "adm_init");
10746 adev->adm_deinit = (adm_deinit_t)
10747 dlsym(adev->adm_lib, "adm_deinit");
10748 adev->adm_register_input_stream = (adm_register_input_stream_t)
10749 dlsym(adev->adm_lib, "adm_register_input_stream");
10750 adev->adm_register_output_stream = (adm_register_output_stream_t)
10751 dlsym(adev->adm_lib, "adm_register_output_stream");
10752 adev->adm_deregister_stream = (adm_deregister_stream_t)
10753 dlsym(adev->adm_lib, "adm_deregister_stream");
10754 adev->adm_request_focus = (adm_request_focus_t)
10755 dlsym(adev->adm_lib, "adm_request_focus");
10756 adev->adm_abandon_focus = (adm_abandon_focus_t)
10757 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010758 adev->adm_set_config = (adm_set_config_t)
10759 dlsym(adev->adm_lib, "adm_set_config");
10760 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10761 dlsym(adev->adm_lib, "adm_request_focus_v2");
10762 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10763 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10764 adev->adm_on_routing_change = (adm_on_routing_change_t)
10765 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010766 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10767 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010768 }
10769 }
10770
Aalique Grahame22e49102018-12-18 14:23:57 -080010771 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010772 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010773 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010774 //initialize this to false for now,
10775 //this will be set to true through set param
10776 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010777
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010778 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010779 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010780
10781 if (k_enable_extended_precision)
10782 adev_verify_devices(adev);
10783
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010784 adev->dsp_bit_width_enforce_mode =
10785 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010786
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010787 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10788 &adev->streams_output_cfg_list,
10789 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010790
Kiran Kandi910e1862013-10-29 13:29:42 -070010791 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010792
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010793 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010794 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010795 trial = atoi(value);
10796 if (period_size_is_plausible_for_low_latency(trial)) {
10797 pcm_config_low_latency.period_size = trial;
10798 pcm_config_low_latency.start_threshold = trial / 4;
10799 pcm_config_low_latency.avail_min = trial / 4;
10800 configured_low_latency_capture_period_size = trial;
10801 }
10802 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010803 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10804 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010805 trial = atoi(value);
10806 if (period_size_is_plausible_for_low_latency(trial)) {
10807 configured_low_latency_capture_period_size = trial;
10808 }
10809 }
10810
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010811 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10812
Eric Laurent4b084132018-10-19 17:33:43 -070010813 adev->camera_orientation = CAMERA_DEFAULT;
10814
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010815 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010816 af_period_multiplier = atoi(value);
10817 if (af_period_multiplier < 0)
10818 af_period_multiplier = 2;
10819 else if (af_period_multiplier > 4)
10820 af_period_multiplier = 4;
10821
10822 ALOGV("new period_multiplier = %d", af_period_multiplier);
10823 }
10824
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010825 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010826
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010827 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010828 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010829 pthread_mutex_unlock(&adev_init_lock);
10830
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010831 if (adev->adm_init)
10832 adev->adm_data = adev->adm_init();
10833
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010834 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010835 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010836
10837 audio_extn_snd_mon_init();
10838 pthread_mutex_lock(&adev->lock);
10839 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10840 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010841 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10842 /*
10843 * if the battery state callback happens before charging can be queried,
10844 * it will be guarded with the adev->lock held in the cb function and so
10845 * the callback value will reflect the latest state
10846 */
10847 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010848 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010849 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010850 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010851 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010852 /* Allocate memory for Device config params */
10853 adev->device_cfg_params = (struct audio_device_config_param*)
10854 calloc(platform_get_max_codec_backend(),
10855 sizeof(struct audio_device_config_param));
10856 if (adev->device_cfg_params == NULL)
10857 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010858
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010859 /*
10860 * Check if new PSPD matrix mixer control is supported. If not
10861 * supported, then set flag so that old mixer ctrl is sent while
10862 * sending pspd coefficients on older kernel version. Query mixer
10863 * control for default pcm id and channel value one.
10864 */
10865 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10866 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10867
10868 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10869 if (!ctl) {
10870 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10871 __func__, mixer_ctl_name);
10872 adev->use_old_pspd_mix_ctrl = true;
10873 }
10874
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010875 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010876 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010877
10878adev_open_err:
10879 free_map(adev->patch_map);
10880 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010881 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010882 pthread_mutex_destroy(&adev->lock);
10883 free(adev);
10884 adev = NULL;
10885 *device = NULL;
10886 pthread_mutex_unlock(&adev_init_lock);
10887 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010888}
10889
10890static struct hw_module_methods_t hal_module_methods = {
10891 .open = adev_open,
10892};
10893
10894struct audio_module HAL_MODULE_INFO_SYM = {
10895 .common = {
10896 .tag = HARDWARE_MODULE_TAG,
10897 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10898 .hal_api_version = HARDWARE_HAL_API_VERSION,
10899 .id = AUDIO_HARDWARE_MODULE_ID,
10900 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010901 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010902 .methods = &hal_module_methods,
10903 },
10904};