blob: c6d34c56f0db20f375ee73e12cacbb4b927270e7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Zhou Song642ec432020-12-23 16:11:10 +08002 * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700151static unsigned int configured_low_latency_capture_period_size =
152 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
153
Haynes Mathew George16081042017-05-31 17:16:49 -0700154#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
155#define MMAP_PERIOD_COUNT_MIN 32
156#define MMAP_PERIOD_COUNT_MAX 512
157#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
158
Aalique Grahame22e49102018-12-18 14:23:57 -0800159/* This constant enables extended precision handling.
160 * TODO The flag is off until more testing is done.
161 */
162static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700163extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800164
Eric Laurentb23d5282013-05-14 15:27:20 -0700165struct pcm_config pcm_config_deep_buffer = {
166 .channels = 2,
167 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
168 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
169 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
172 .stop_threshold = INT_MAX,
173 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
174};
175
176struct pcm_config pcm_config_low_latency = {
177 .channels = 2,
178 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
179 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
180 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
183 .stop_threshold = INT_MAX,
184 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185};
186
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800187struct pcm_config pcm_config_haptics_audio = {
188 .channels = 1,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
191 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
194 .stop_threshold = INT_MAX,
195 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
196};
197
198struct pcm_config pcm_config_haptics = {
199 .channels = 1,
200 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
201 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
202 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
203 .format = PCM_FORMAT_S16_LE,
204 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .stop_threshold = INT_MAX,
206 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209static int af_period_multiplier = 4;
210struct pcm_config pcm_config_rt = {
211 .channels = 2,
212 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
213 .period_size = ULL_PERIOD_SIZE, //1 ms
214 .period_count = 512, //=> buffer size is 512ms
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
217 .stop_threshold = INT_MAX,
218 .silence_threshold = 0,
219 .silence_size = 0,
220 .avail_min = ULL_PERIOD_SIZE, //1 ms
221};
222
Eric Laurentb23d5282013-05-14 15:27:20 -0700223struct pcm_config pcm_config_hdmi_multi = {
224 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
225 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
226 .period_size = HDMI_MULTI_PERIOD_SIZE,
227 .period_count = HDMI_MULTI_PERIOD_COUNT,
228 .format = PCM_FORMAT_S16_LE,
229 .start_threshold = 0,
230 .stop_threshold = INT_MAX,
231 .avail_min = 0,
232};
233
Haynes Mathew George16081042017-05-31 17:16:49 -0700234struct pcm_config pcm_config_mmap_playback = {
235 .channels = 2,
236 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
237 .period_size = MMAP_PERIOD_SIZE,
238 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
239 .format = PCM_FORMAT_S16_LE,
240 .start_threshold = MMAP_PERIOD_SIZE*8,
241 .stop_threshold = INT32_MAX,
242 .silence_threshold = 0,
243 .silence_size = 0,
244 .avail_min = MMAP_PERIOD_SIZE, //1 ms
245};
246
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700247struct pcm_config pcm_config_hifi = {
248 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
249 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
250 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
251 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
252 .format = PCM_FORMAT_S24_3LE,
253 .start_threshold = 0,
254 .stop_threshold = INT_MAX,
255 .avail_min = 0,
256};
257
Eric Laurentb23d5282013-05-14 15:27:20 -0700258struct pcm_config pcm_config_audio_capture = {
259 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
261 .format = PCM_FORMAT_S16_LE,
262};
263
Haynes Mathew George16081042017-05-31 17:16:49 -0700264struct pcm_config pcm_config_mmap_capture = {
265 .channels = 2,
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
267 .period_size = MMAP_PERIOD_SIZE,
268 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
269 .format = PCM_FORMAT_S16_LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .silence_threshold = 0,
273 .silence_size = 0,
274 .avail_min = MMAP_PERIOD_SIZE, //1 ms
275};
276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700277#define AFE_PROXY_CHANNEL_COUNT 2
278#define AFE_PROXY_SAMPLING_RATE 48000
279
280#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
281#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
282
283struct pcm_config pcm_config_afe_proxy_playback = {
284 .channels = AFE_PROXY_CHANNEL_COUNT,
285 .rate = AFE_PROXY_SAMPLING_RATE,
286 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
287 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
288 .format = PCM_FORMAT_S16_LE,
289 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
290 .stop_threshold = INT_MAX,
291 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
292};
293
294#define AFE_PROXY_RECORD_PERIOD_SIZE 768
295#define AFE_PROXY_RECORD_PERIOD_COUNT 4
296
Aalique Grahame22e49102018-12-18 14:23:57 -0800297struct pcm_config pcm_config_audio_capture_rt = {
298 .channels = 2,
299 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
300 .period_size = ULL_PERIOD_SIZE,
301 .period_count = 512,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = 0,
304 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
305 .silence_threshold = 0,
306 .silence_size = 0,
307 .avail_min = ULL_PERIOD_SIZE, //1 ms
308};
309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700310struct pcm_config pcm_config_afe_proxy_record = {
311 .channels = AFE_PROXY_CHANNEL_COUNT,
312 .rate = AFE_PROXY_SAMPLING_RATE,
313 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
314 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
315 .format = PCM_FORMAT_S16_LE,
316 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
317 .stop_threshold = INT_MAX,
318 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
319};
320
Ashish Jainf1eaa582016-05-23 20:54:24 +0530321#define AUDIO_MAX_PCM_FORMATS 7
322
323const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
324 [AUDIO_FORMAT_DEFAULT] = 0,
325 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
326 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
327 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
329 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
330 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
331};
332
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800333const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700334 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
335 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800336 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800337 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700338 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
339 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700340 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700341 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
349 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700350 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
351 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700352 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800353 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700354
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700356 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530357 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
358 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
359 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530360 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
361 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700363 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700364 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700365 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700366
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800367 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800368 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400369 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
370 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700371
Derek Chenf7092792017-05-23 12:23:53 -0400372 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700373 [USECASE_VOICE2_CALL] = "voice2-call",
374 [USECASE_VOLTE_CALL] = "volte-call",
375 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800376 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800377 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
378 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800379 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700380 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
381 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
382 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800383 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
384 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
385 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
386
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700387 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
388 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700389 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
390 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700391
392 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
393 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800394 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530395 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700396
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530397 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
399 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700400
401 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
402 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530403 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530404 /* For Interactive Audio Streams */
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
412 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700413
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800414 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
415
Derek Chenf6318be2017-06-12 17:16:24 -0400416 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
417
418 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
419 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
420 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
421 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800422 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700423 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530424 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500425 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400426
427 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
428 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
429 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800430 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500431 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700432};
433
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700434static const audio_usecase_t offload_usecases[] = {
435 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
441 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
442 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
443 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700444};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445
Varun Balaraje49253e2017-07-06 19:48:56 +0530446static const audio_usecase_t interactive_usecases[] = {
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
452 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
453 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
454 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
455};
456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457#define STRING_TO_ENUM(string) { #string, string }
458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800459struct string_to_enum {
460 const char *name;
461 uint32_t value;
462};
463
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800470 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
471 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800472 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700473 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
474 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
475 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
481 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
482 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
483 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum formats_name_to_enum_table[] = {
487 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
488 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
489 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700490 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
491 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
492 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700493 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800494 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
495 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700496 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800497};
498
499//list of all supported sample rates by HDMI specification.
500static const int out_hdmi_sample_rates[] = {
501 32000, 44100, 48000, 88200, 96000, 176400, 192000,
502};
503
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700504static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800505 STRING_TO_ENUM(32000),
506 STRING_TO_ENUM(44100),
507 STRING_TO_ENUM(48000),
508 STRING_TO_ENUM(88200),
509 STRING_TO_ENUM(96000),
510 STRING_TO_ENUM(176400),
511 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800512 STRING_TO_ENUM(352800),
513 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700514};
515
Carter Hsu2e429db2019-05-14 18:50:52 +0800516struct in_effect_list {
517 struct listnode list;
518 effect_handle_t handle;
519};
520
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700521static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700522static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700523static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700524//cache last MBDRC cal step level
525static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700526
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530527static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700528static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800529static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530530static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530531
Derek Chen6f293672019-04-01 01:40:24 -0700532static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
533static void in_snd_mon_cb(void * stream, struct str_parms * parms);
534static void out_snd_mon_cb(void * stream, struct str_parms * parms);
535
Zhou Song331c8e52019-08-26 14:16:12 +0800536static int configure_btsco_sample_rate(snd_device_t snd_device);
537
Vatsal Buchac09ae062018-11-14 13:25:08 +0530538#ifdef AUDIO_FEATURE_ENABLED_GCOV
539extern void __gcov_flush();
540static void enable_gcov()
541{
542 __gcov_flush();
543}
544#else
545static void enable_gcov()
546{
547}
548#endif
549
justinweng20fb6d82019-02-21 18:49:00 -0700550static int in_set_microphone_direction(const struct audio_stream_in *stream,
551 audio_microphone_direction_t dir);
552static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
553
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700554static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
555 int flags __unused)
556{
557 int dir = 0;
558 switch (uc_id) {
559 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530560 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700561 dir = 1;
562 case USECASE_AUDIO_PLAYBACK_ULL:
563 break;
564 default:
565 return false;
566 }
567
568 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
569 PCM_PLAYBACK : PCM_CAPTURE);
570 if (adev->adm_is_noirq_avail)
571 return adev->adm_is_noirq_avail(adev->adm_data,
572 adev->snd_card, dev_id, dir);
573 return false;
574}
575
576static void register_out_stream(struct stream_out *out)
577{
578 struct audio_device *adev = out->dev;
579 if (is_offload_usecase(out->usecase) ||
580 !adev->adm_register_output_stream)
581 return;
582
583 // register stream first for backward compatibility
584 adev->adm_register_output_stream(adev->adm_data,
585 out->handle,
586 out->flags);
587
588 if (!adev->adm_set_config)
589 return;
590
591 if (out->realtime)
592 adev->adm_set_config(adev->adm_data,
593 out->handle,
594 out->pcm, &out->config);
595}
596
597static void register_in_stream(struct stream_in *in)
598{
599 struct audio_device *adev = in->dev;
600 if (!adev->adm_register_input_stream)
601 return;
602
603 adev->adm_register_input_stream(adev->adm_data,
604 in->capture_handle,
605 in->flags);
606
607 if (!adev->adm_set_config)
608 return;
609
610 if (in->realtime)
611 adev->adm_set_config(adev->adm_data,
612 in->capture_handle,
613 in->pcm,
614 &in->config);
615}
616
617static void request_out_focus(struct stream_out *out, long ns)
618{
619 struct audio_device *adev = out->dev;
620
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 if (adev->adm_request_focus_v2)
622 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
623 else if (adev->adm_request_focus)
624 adev->adm_request_focus(adev->adm_data, out->handle);
625}
626
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700627static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628{
629 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700630 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700632 if (adev->adm_request_focus_v2_1)
633 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
634 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700635 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
636 else if (adev->adm_request_focus)
637 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700638
639 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700640}
641
642static void release_out_focus(struct stream_out *out)
643{
644 struct audio_device *adev = out->dev;
645
646 if (adev->adm_abandon_focus)
647 adev->adm_abandon_focus(adev->adm_data, out->handle);
648}
649
650static void release_in_focus(struct stream_in *in)
651{
652 struct audio_device *adev = in->dev;
653 if (adev->adm_abandon_focus)
654 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
655}
656
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530657static int parse_snd_card_status(struct str_parms *parms, int *card,
658 card_status_t *status)
659{
660 char value[32]={0};
661 char state[32]={0};
662
663 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
664 if (ret < 0)
665 return -1;
666
667 // sscanf should be okay as value is of max length 32.
668 // same as sizeof state.
669 if (sscanf(value, "%d,%s", card, state) < 2)
670 return -1;
671
672 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
673 CARD_STATUS_OFFLINE;
674 return 0;
675}
676
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700677static inline void adjust_frames_for_device_delay(struct stream_out *out,
678 uint32_t *dsp_frames) {
679 // Adjustment accounts for A2dp encoder latency with offload usecases
680 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800681 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700682 unsigned long offset =
683 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
684 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
685 }
686}
687
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700688static inline bool free_entry(void *key __unused,
689 void *value, void *context __unused)
690{
691 free(value);
692 return true;
693}
694
695static inline void free_map(Hashmap *map)
696{
697 if (map) {
698 hashmapForEach(map, free_entry, (void *) NULL);
699 hashmapFree(map);
700 }
701}
702
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800703static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700704 audio_patch_handle_t patch_handle)
705{
706 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
707 return;
708
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700709 struct audio_patch_info *p_info =
710 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
711 if (p_info) {
712 ALOGV("%s: Remove patch %d", __func__, patch_handle);
713 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
714 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715 free(p_info);
716 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700717}
718
719static inline int io_streams_map_insert(struct audio_device *adev,
720 struct audio_stream *stream,
721 audio_io_handle_t handle,
722 audio_patch_handle_t patch_handle)
723{
724 struct audio_stream_info *s_info =
725 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
726
727 if (s_info == NULL) {
728 ALOGE("%s: Could not allocate stream info", __func__);
729 return -ENOMEM;
730 }
731 s_info->stream = stream;
732 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700733
734 pthread_mutex_lock(&adev->lock);
735 struct audio_stream_info *stream_info =
736 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700737 if (stream_info != NULL)
738 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700740 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 return 0;
742}
743
744static inline void io_streams_map_remove(struct audio_device *adev,
745 audio_io_handle_t handle)
746{
747 pthread_mutex_lock(&adev->lock);
748 struct audio_stream_info *s_info =
749 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700752 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800755done:
756 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return;
758}
759
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800760static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700761 audio_patch_handle_t handle)
762{
763 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700764 p_info = (struct audio_patch_info *)
765 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700766 return p_info;
767}
768
vivek mehtaa76401a2015-04-24 14:12:15 -0700769__attribute__ ((visibility ("default")))
770bool audio_hw_send_gain_dep_calibration(int level) {
771 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700772 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700773
774 pthread_mutex_lock(&adev_init_lock);
775
776 if (adev != NULL && adev->platform != NULL) {
777 pthread_mutex_lock(&adev->lock);
778 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700779
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530780 // cache level info for any of the use case which
781 // was not started.
782 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700783
vivek mehtaa76401a2015-04-24 14:12:15 -0700784 pthread_mutex_unlock(&adev->lock);
785 } else {
786 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
787 }
788
789 pthread_mutex_unlock(&adev_init_lock);
790
791 return ret_val;
792}
793
Ashish Jain5106d362016-05-11 19:23:33 +0530794static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
795{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796 bool gapless_enabled = false;
797 const char *mixer_ctl_name = "Compress Gapless Playback";
798 struct mixer_ctl *ctl;
799
800 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700801 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530802
803 /*Disable gapless if its AV playback*/
804 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800805
806 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
807 if (!ctl) {
808 ALOGE("%s: Could not get ctl for mixer cmd - %s",
809 __func__, mixer_ctl_name);
810 return -EINVAL;
811 }
812
813 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
814 ALOGE("%s: Could not set gapless mode %d",
815 __func__, gapless_enabled);
816 return -EINVAL;
817 }
818 return 0;
819}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700820
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700821__attribute__ ((visibility ("default")))
822int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
823 int table_size) {
824 int ret_val = 0;
825 ALOGV("%s: enter ... ", __func__);
826
827 pthread_mutex_lock(&adev_init_lock);
828 if (adev == NULL) {
829 ALOGW("%s: adev is NULL .... ", __func__);
830 goto done;
831 }
832
833 pthread_mutex_lock(&adev->lock);
834 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
835 pthread_mutex_unlock(&adev->lock);
836done:
837 pthread_mutex_unlock(&adev_init_lock);
838 ALOGV("%s: exit ... ", __func__);
839 return ret_val;
840}
841
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800843{
844 bool ret = false;
845 ALOGV("%s: enter ...", __func__);
846
847 pthread_mutex_lock(&adev_init_lock);
848
849 if (adev != NULL && adev->platform != NULL) {
850 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800851 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800852 pthread_mutex_unlock(&adev->lock);
853 }
854
855 pthread_mutex_unlock(&adev_init_lock);
856
857 ALOGV("%s: exit with ret %d", __func__, ret);
858 return ret;
859}
Aalique Grahame22e49102018-12-18 14:23:57 -0800860
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700861static bool is_supported_format(audio_format_t format)
862{
Eric Laurent86e17132013-09-12 17:49:30 -0700863 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530864 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530865 format == AUDIO_FORMAT_AAC_LC ||
866 format == AUDIO_FORMAT_AAC_HE_V1 ||
867 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530868 format == AUDIO_FORMAT_AAC_ADTS_LC ||
869 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
870 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530871 format == AUDIO_FORMAT_AAC_LATM_LC ||
872 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
873 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530874 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
875 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530876 format == AUDIO_FORMAT_PCM_FLOAT ||
877 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700878 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530879 format == AUDIO_FORMAT_AC3 ||
880 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700881 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530882 format == AUDIO_FORMAT_DTS ||
883 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800884 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530885 format == AUDIO_FORMAT_ALAC ||
886 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530887 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530888 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800889 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530890 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700891 format == AUDIO_FORMAT_APTX ||
892 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800893 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700894
895 return false;
896}
897
Kunlei Zhang67cc7072020-12-18 17:16:49 +0800898static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
899{
900 struct listnode *node;
901 struct audio_usecase *usecase;
902
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
905 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
906 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
907 return false;
908 }
909 }
910
911 return true;
912}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700913static inline bool is_mmap_usecase(audio_usecase_t uc_id)
914{
915 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800916 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700917 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
918}
919
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700920static inline bool is_valid_volume(float left, float right)
921{
922 return ((left >= 0.0f && right >= 0.0f) ? true : false);
923}
924
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530925static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530926{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530927 ALOGV("%s", __func__);
928 audio_route_apply_and_update_path(adev->audio_route,
929 "asrc-mode");
930 adev->asrc_mode_enabled = true;
931}
932
933static void disable_asrc_mode(struct audio_device *adev)
934{
935 ALOGV("%s", __func__);
936 audio_route_reset_and_update_path(adev->audio_route,
937 "asrc-mode");
938 adev->asrc_mode_enabled = false;
939}
940
Saurav Kumarc1411662020-10-14 10:50:45 +0530941static void check_and_configure_headphone(struct audio_device *adev,
942 struct audio_usecase *uc_info,
943 snd_device_t snd_device)
944{
945 struct listnode *node;
946 struct audio_usecase *usecase;
947 int new_backend_idx, usecase_backend_idx;
948 bool spkr_hph_single_be_native_concurrency;
949
950 new_backend_idx = platform_get_backend_index(snd_device);
951 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +0800952 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
953 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +0530954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
957 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
958 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
959 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
960 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->out_snd_device);
963 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530964 platform_check_and_set_codec_backend_cfg(adev, usecase,
965 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530966 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +0800967 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +0530968 }
969 }
Revathi Uddaraju2c0eac02021-07-27 02:06:42 -0700970 else if ((usecase->type != PCM_CAPTURE) && (usecase == uc_info)) {
971 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
972 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
973 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
974 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
975 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
976 platform_check_and_set_codec_backend_cfg(adev, usecase,
977 usecase->out_snd_device);
978 }
979 }
Saurav Kumarc1411662020-10-14 10:50:45 +0530980 }
981 }
982}
983
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530984/*
985 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
986 * 44.1 or Native DSD backends are enabled for any of current use case.
987 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
988 * - Disable current mix path use case(Headphone backend) and re-enable it with
989 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
990 * e.g. Naitve DSD or Headphone 44.1 -> + 48
991 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530992static void check_and_set_asrc_mode(struct audio_device *adev,
993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530995{
996 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530997 int i, num_new_devices = 0;
998 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
999 /*
1000 *Split snd device for new combo use case
1001 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
1002 */
1003 if (platform_split_snd_device(adev->platform,
1004 snd_device,
1005 &num_new_devices,
1006 split_new_snd_devices) == 0) {
1007 for (i = 0; i < num_new_devices; i++)
1008 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
1009 } else {
1010 int new_backend_idx = platform_get_backend_index(snd_device);
1011 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1012 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1013 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1014 !adev->asrc_mode_enabled) {
1015 struct listnode *node = NULL;
1016 struct audio_usecase *uc = NULL;
1017 struct stream_out *curr_out = NULL;
1018 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1019 int i, num_devices, ret = 0;
1020 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301021
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301022 list_for_each(node, &adev->usecase_list) {
1023 uc = node_to_item(node, struct audio_usecase, list);
1024 curr_out = (struct stream_out*) uc->stream.out;
1025 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1026 /*
1027 *Split snd device for existing combo use case
1028 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1029 */
1030 ret = platform_split_snd_device(adev->platform,
1031 uc->out_snd_device,
1032 &num_devices,
1033 split_snd_devices);
1034 if (ret < 0 || num_devices == 0) {
1035 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1036 split_snd_devices[0] = uc->out_snd_device;
1037 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001038 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301039 for (i = 0; i < num_devices; i++) {
1040 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1041 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1042 if((new_backend_idx == HEADPHONE_BACKEND) &&
1043 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1044 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001045 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301046 __func__);
1047 enable_asrc_mode(adev);
1048 break;
1049 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1050 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1051 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001052 ALOGV("%s: 48K stream detected, disabling and enabling it \
1053 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301054 disable_audio_route(adev, uc);
1055 disable_snd_device(adev, uc->out_snd_device);
1056 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1057 if (new_backend_idx == DSD_NATIVE_BACKEND)
1058 audio_route_apply_and_update_path(adev->audio_route,
1059 "hph-true-highquality-mode");
1060 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1061 (curr_out->bit_width >= 24))
1062 audio_route_apply_and_update_path(adev->audio_route,
1063 "hph-highquality-mode");
1064 enable_asrc_mode(adev);
1065 enable_snd_device(adev, uc->out_snd_device);
1066 enable_audio_route(adev, uc);
1067 break;
1068 }
1069 }
1070 // reset split devices count
1071 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001072 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301073 if (adev->asrc_mode_enabled)
1074 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301075 }
1076 }
1077 }
1078}
1079
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001080static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1081 struct audio_effect_config effect_config,
1082 unsigned int param_value)
1083{
1084 char mixer_ctl_name[] = "Audio Effect";
1085 struct mixer_ctl *ctl;
1086 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001087 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001088
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001089 if (in == NULL) {
1090 ALOGE("%s: active input stream is NULL", __func__);
1091 return -EINVAL;
1092 }
1093
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001094 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1095 if (!ctl) {
1096 ALOGE("%s: Could not get mixer ctl - %s",
1097 __func__, mixer_ctl_name);
1098 return -EINVAL;
1099 }
1100
1101 set_values[0] = 1; //0:Rx 1:Tx
1102 set_values[1] = in->app_type_cfg.app_type;
1103 set_values[2] = (long)effect_config.module_id;
1104 set_values[3] = (long)effect_config.instance_id;
1105 set_values[4] = (long)effect_config.param_id;
1106 set_values[5] = param_value;
1107
1108 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1109
1110 return 0;
1111
1112}
1113
1114static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1115 int effect_type, unsigned int *param_value)
1116{
1117 int ret = 0;
1118 struct audio_effect_config other_effect_config;
1119 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001120 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001121
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001122 if (in == NULL) {
1123 ALOGE("%s: active input stream is NULL", __func__);
1124 return -EINVAL;
1125 }
1126
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001127 usecase = get_usecase_from_list(adev, in->usecase);
1128 if (!usecase)
1129 return -EINVAL;
1130
1131 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1132 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1133 if (ret < 0) {
1134 ALOGE("%s Failed to get effect params %d", __func__, ret);
1135 return ret;
1136 }
1137
1138 if (module_id == other_effect_config.module_id) {
1139 //Same module id for AEC/NS. Values need to be combined
1140 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1141 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1142 *param_value |= other_effect_config.param_value;
1143 }
1144 }
1145
1146 return ret;
1147}
1148
1149static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301150{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001151 struct audio_effect_config effect_config;
1152 struct audio_usecase *usecase = NULL;
1153 int ret = 0;
1154 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001155 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001157 if(!voice_extn_is_dynamic_ecns_enabled())
1158 return ENOSYS;
1159
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001160 if (!in) {
1161 ALOGE("%s: Invalid input stream", __func__);
1162 return -EINVAL;
1163 }
1164
1165 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1166
1167 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001168 if (usecase == NULL) {
1169 ALOGE("%s: Could not find the usecase (%d) in the list",
1170 __func__, in->usecase);
1171 return -EINVAL;
1172 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001173
1174 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1175 if (ret < 0) {
1176 ALOGE("%s Failed to get module id %d", __func__, ret);
1177 return ret;
1178 }
1179 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1180 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1181
1182 if(enable)
1183 param_value = effect_config.param_value;
1184
1185 /*Special handling for AEC & NS effects Param values need to be
1186 updated if module ids are same*/
1187
1188 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1189 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1190 if (ret < 0)
1191 return ret;
1192 }
1193
1194 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1195
1196 return ret;
1197}
1198
1199static void check_and_enable_effect(struct audio_device *adev)
1200{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001201 if(!voice_extn_is_dynamic_ecns_enabled())
1202 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001203
Eric Laurent637e2d42018-11-15 12:24:31 -08001204 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001205
Eric Laurent637e2d42018-11-15 12:24:31 -08001206 if (in != NULL && !in->standby) {
1207 if (in->enable_aec)
1208 enable_disable_effect(adev, EFFECT_AEC, true);
1209
1210 if (in->enable_ns &&
1211 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1212 enable_disable_effect(adev, EFFECT_NS, true);
1213 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001214 }
1215}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001216
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001217int pcm_ioctl(struct pcm *pcm, int request, ...)
1218{
1219 va_list ap;
1220 void * arg;
1221 int pcm_fd = *(int*)pcm;
1222
1223 va_start(ap, request);
1224 arg = va_arg(ap, void *);
1225 va_end(ap);
1226
1227 return ioctl(pcm_fd, request, arg);
1228}
1229
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001230int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001231 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001233 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001234 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301235 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301236 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001237 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301238 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001239
1240 if (usecase == NULL)
1241 return -EINVAL;
1242
1243 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1244
Carter Hsu2e429db2019-05-14 18:50:52 +08001245 if (usecase->type == PCM_CAPTURE) {
1246 struct stream_in *in = usecase->stream.in;
1247 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001248 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001249
1250 if (in) {
1251 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001252 list_init(&out_devices);
1253 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001254 struct listnode *node;
1255 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1256 USECASE_AUDIO_PLAYBACK_VOIP);
1257 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001258 assign_devices(&out_devices,
1259 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001260 } else if (adev->primary_output &&
1261 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001262 assign_devices(&out_devices,
1263 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001264 } else {
1265 list_for_each(node, &adev->usecase_list) {
1266 uinfo = node_to_item(node, struct audio_usecase, list);
1267 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001268 assign_devices(&out_devices,
1269 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001270 break;
1271 }
1272 }
1273 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001274
1275 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001276 in->ec_opened = true;
1277 }
1278 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001279 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1280 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1281 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001282 snd_device = usecase->in_snd_device;
1283 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001285 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001286
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001287 if (usecase->type == PCM_CAPTURE) {
1288 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1289 platform_set_fluence_nn_state(adev->platform, true);
1290 ALOGD("%s: set fluence nn capture state", __func__);
1291 }
1292 }
1293
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001294#ifdef DS1_DOLBY_DAP_ENABLED
1295 audio_extn_dolby_set_dmid(adev);
1296 audio_extn_dolby_set_endpoint(adev);
1297#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001298 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001299 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301300 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001301 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001302 if (audio_extn_is_maxx_audio_enabled())
1303 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301304 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001305 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1306 out = usecase->stream.out;
1307 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301308 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1309 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301310
1311 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001312 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1313 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1314 adev->fluence_nn_usecase_id = usecase->id;
1315 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1316 }
1317 }
1318
1319 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301320 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001321 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301322 ALOGD("%s: set custom mtmx params v1", __func__);
1323 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1324 }
1325 } else {
1326 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1327 }
Manish Dewangan58229382017-02-02 15:48:41 +05301328
Andy Hung756ecc12018-10-19 17:47:12 -07001329 // we shouldn't truncate mixer_path
1330 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1331 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1332 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001333 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001334 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301335 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1336 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1337 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1338 if (parms) {
1339 audio_extn_fm_set_parameters(adev, parms);
1340 str_parms_destroy(parms);
1341 }
1342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 ALOGV("%s: exit", __func__);
1344 return 0;
1345}
1346
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001347int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001348 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001351 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301352 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001353
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301354 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001355 return -EINVAL;
1356
1357 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301358 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 snd_device = usecase->in_snd_device;
1360 else
1361 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001362
1363 /* disable island and power mode on supported device for voice call */
1364 if (usecase->type == VOICE_CALL) {
1365 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1366 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1367 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1368 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1369 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1370 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001371 if (voice_is_lte_call_active(adev))
1372 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001373 ALOGD("%s: disable island cfg and power mode in voice tx path",
1374 __func__);
1375 }
1376 }
1377 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1378 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1379 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1380 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1381 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1382 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1383 ALOGD("%s: disable island cfg and power mode in voice rx path",
1384 __func__);
1385 }
1386 }
1387 }
1388
Andy Hung756ecc12018-10-19 17:47:12 -07001389 // we shouldn't truncate mixer_path
1390 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1391 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1392 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001393 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001394 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001395 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001396 if (usecase->type == PCM_CAPTURE) {
1397 struct stream_in *in = usecase->stream.in;
1398 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001399 struct listnode out_devices;
1400 list_init(&out_devices);
1401 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001402 in->ec_opened = false;
1403 }
1404 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001405 if (usecase->id == adev->fluence_nn_usecase_id) {
1406 platform_set_fluence_nn_state(adev->platform, false);
1407 adev->fluence_nn_usecase_id = USECASE_INVALID;
1408 ALOGD("%s: reset fluence nn capture state", __func__);
1409 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001410 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301411 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301412
1413 if (usecase->type == PCM_CAPTURE) {
1414 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001415 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301416 ALOGD("%s: reset custom mtmx params v1", __func__);
1417 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1418 }
1419 } else {
1420 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1421 }
1422
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001423 if ((usecase->type == PCM_PLAYBACK) &&
1424 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301425 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 ALOGV("%s: exit", __func__);
1428 return 0;
1429}
1430
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001431int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001432 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301434 int i, num_devices = 0;
1435 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001436 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1437
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001438 if (snd_device < SND_DEVICE_MIN ||
1439 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001440 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001441 return -EINVAL;
1442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001445 ALOGE("%s: Invalid sound device returned", __func__);
1446 return -EINVAL;
1447 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001448
1449 adev->snd_dev_ref_cnt[snd_device]++;
1450
1451 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1452 (platform_split_snd_device(adev->platform,
1453 snd_device,
1454 &num_devices,
1455 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001456 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001457 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001458 /* Set backend config for A2DP to ensure slimbus configuration
1459 is correct if A2DP is already active and backend is closed
1460 and re-opened */
1461 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1462 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 return 0;
1464 }
1465
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001466 if (audio_extn_spkr_prot_is_enabled())
1467 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001468
Aalique Grahame22e49102018-12-18 14:23:57 -08001469 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1470
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001471 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1472 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001473 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1474 goto err;
1475 }
1476 audio_extn_dev_arbi_acquire(snd_device);
1477 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001478 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001479 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001480 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001481 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001482 } else if (platform_split_snd_device(adev->platform,
1483 snd_device,
1484 &num_devices,
1485 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 for (i = 0; i < num_devices; i++) {
1487 enable_snd_device(adev, new_snd_devices[i]);
1488 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001489 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001490 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001491 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301492
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001493 /* enable island and power mode on supported device */
1494 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1495 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1496 platform_set_island_cfg_on_device(adev, snd_device, true);
1497 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001498 if (voice_is_lte_call_active(adev) &&
1499 (snd_device >= SND_DEVICE_IN_BEGIN &&
1500 snd_device < SND_DEVICE_IN_END))
1501 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001502 ALOGD("%s: enable island cfg and power mode on: %s",
1503 __func__, device_name);
1504 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301505
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301506 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1507 if (audio_extn_a2dp_start_playback() < 0) {
1508 ALOGE(" fail to configure A2dp Source control path ");
1509 goto err;
1510 } else {
1511 adev->a2dp_started = true;
1512 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001514
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001515 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1516 (audio_extn_a2dp_start_capture() < 0)) {
1517 ALOGE(" fail to configure A2dp Sink control path ");
1518 goto err;
1519 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301520
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001521 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1522 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1523 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1524 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1525 ALOGE(" fail to configure sco control path ");
1526 goto err;
1527 }
Zhou Song12c29502019-03-16 10:37:18 +08001528 }
1529
Zhou Song331c8e52019-08-26 14:16:12 +08001530 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001531 /* due to the possibility of calibration overwrite between listen
1532 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001533 audio_extn_sound_trigger_update_device_status(snd_device,
1534 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301535 audio_extn_listen_update_device_status(snd_device,
1536 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001537 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001538 audio_extn_sound_trigger_update_device_status(snd_device,
1539 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301540 audio_extn_listen_update_device_status(snd_device,
1541 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001542 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001543 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001544 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001545 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301546
1547 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1548 !adev->native_playback_enabled &&
1549 audio_is_true_native_stream_active(adev)) {
1550 ALOGD("%s: %d: napb: enabling native mode in hardware",
1551 __func__, __LINE__);
1552 audio_route_apply_and_update_path(adev->audio_route,
1553 "true-native-mode");
1554 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301555 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301556 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1557 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001558 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001559 ALOGD("%s: init ec ref loopback", __func__);
1560 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001564err:
1565 adev->snd_dev_ref_cnt[snd_device]--;
1566 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567}
1568
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001569int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001570 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301572 int i, num_devices = 0;
1573 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001574 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1575
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001576 if (snd_device < SND_DEVICE_MIN ||
1577 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001578 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001579 return -EINVAL;
1580 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001581
1582 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1583 ALOGE("%s: Invalid sound device returned", __func__);
1584 return -EINVAL;
1585 }
1586
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1588 ALOGE("%s: device ref cnt is already 0", __func__);
1589 return -EINVAL;
1590 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001591
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001593
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001595 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001596 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301597
Aalique Grahame22e49102018-12-18 14:23:57 -08001598 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1599
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001600 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1601 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001602 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001603
1604 // when speaker device is disabled, reset swap.
1605 // will be renabled on usecase start
1606 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001607 } else if (platform_split_snd_device(adev->platform,
1608 snd_device,
1609 &num_devices,
1610 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301611 for (i = 0; i < num_devices; i++) {
1612 disable_snd_device(adev, new_snd_devices[i]);
1613 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001614 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001615 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001616 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001617 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001618
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301619 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301620 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301621 adev->a2dp_started = false;
1622 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001623 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001624 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001625 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301626 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001627 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301628 adev->native_playback_enabled) {
1629 ALOGD("%s: %d: napb: disabling native mode in hardware",
1630 __func__, __LINE__);
1631 audio_route_reset_and_update_path(adev->audio_route,
1632 "true-native-mode");
1633 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001634 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301635 adev->asrc_mode_enabled) {
1636 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301637 disable_asrc_mode(adev);
1638 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001639 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301640 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001641 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001642 ALOGD("%s: deinit ec ref loopback", __func__);
1643 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1644 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001645
1646 audio_extn_utils_release_snd_device(snd_device);
1647 } else {
1648 if (platform_split_snd_device(adev->platform,
1649 snd_device,
1650 &num_devices,
1651 new_snd_devices) == 0) {
1652 for (i = 0; i < num_devices; i++) {
1653 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1654 }
1655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001656 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 return 0;
1659}
1660
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001661/*
1662 legend:
1663 uc - existing usecase
1664 new_uc - new usecase
1665 d1, d11, d2 - SND_DEVICE enums
1666 a1, a2 - corresponding ANDROID device enums
1667 B1, B2 - backend strings
1668
1669case 1
1670 uc->dev d1 (a1) B1
1671 new_uc->dev d1 (a1), d2 (a2) B1, B2
1672
1673 resolution: disable and enable uc->dev on d1
1674
1675case 2
1676 uc->dev d1 (a1) B1
1677 new_uc->dev d11 (a1) B1
1678
1679 resolution: need to switch uc since d1 and d11 are related
1680 (e.g. speaker and voice-speaker)
1681 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1682
1683case 3
1684 uc->dev d1 (a1) B1
1685 new_uc->dev d2 (a2) B2
1686
1687 resolution: no need to switch uc
1688
1689case 4
1690 uc->dev d1 (a1) B1
1691 new_uc->dev d2 (a2) B1
1692
1693 resolution: disable enable uc-dev on d2 since backends match
1694 we cannot enable two streams on two different devices if they
1695 share the same backend. e.g. if offload is on speaker device using
1696 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1697 using the same backend, offload must also be switched to voice-handset.
1698
1699case 5
1700 uc->dev d1 (a1) B1
1701 new_uc->dev d1 (a1), d2 (a2) B1
1702
1703 resolution: disable enable uc-dev on d2 since backends match
1704 we cannot enable two streams on two different devices if they
1705 share the same backend.
1706
1707case 6
1708 uc->dev d1 (a1) B1
1709 new_uc->dev d2 (a1) B2
1710
1711 resolution: no need to switch
1712
1713case 7
1714 uc->dev d1 (a1), d2 (a2) B1, B2
1715 new_uc->dev d1 (a1) B1
1716
1717 resolution: no need to switch
1718
Zhou Song4ba65882018-07-09 14:48:07 +08001719case 8
1720 uc->dev d1 (a1) B1
1721 new_uc->dev d11 (a1), d2 (a2) B1, B2
1722 resolution: compared to case 1, for this case, d1 and d11 are related
1723 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301724
1725case 9
1726 uc->dev d1 (a1), d2(a2) B1 B2
1727 new_uc->dev d1 (a1), d22 (a2) B1, B2
1728 resolution: disable enable uc-dev on d2 since backends match
1729 we cannot enable two streams on two different devices if they
1730 share the same backend. This is special case for combo use case
1731 with a2dp and sco devices which uses same backend.
1732 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001733*/
1734static snd_device_t derive_playback_snd_device(void * platform,
1735 struct audio_usecase *uc,
1736 struct audio_usecase *new_uc,
1737 snd_device_t new_snd_device)
1738{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001739 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001740
1741 snd_device_t d1 = uc->out_snd_device;
1742 snd_device_t d2 = new_snd_device;
1743
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001744 list_init(&a1);
1745 list_init(&a2);
1746
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301747 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301748 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001749 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1750 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301751 break;
1752 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001753 assign_devices(&a1, &uc->stream.out->device_list);
1754 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301755 break;
1756 }
1757
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001758 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001759 if (!compare_devices(&a1, &a2) &&
1760 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001761 snd_device_t d3[2];
1762 int num_devices = 0;
1763 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001764 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001765 &num_devices,
1766 d3);
1767 if (ret < 0) {
1768 if (ret != -ENOSYS) {
1769 ALOGW("%s failed to split snd_device %d",
1770 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001771 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001772 }
1773 goto end;
1774 }
1775
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001776 if (platform_check_backends_match(d3[0], d3[1])) {
1777 return d2; // case 5
1778 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301779 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1780 platform_check_backends_match(d1, d2))
1781 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001782 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301783 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001784 // check if d1 is related to any of d3's
1785 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001786 return d1; // case 1
1787 else
1788 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001789 }
1790 } else {
1791 if (platform_check_backends_match(d1, d2)) {
1792 return d2; // case 2, 4
1793 } else {
1794 return d1; // case 6, 3
1795 }
1796 }
1797
1798end:
1799 return d2; // return whatever was calculated before.
1800}
1801
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301803 struct audio_usecase *uc_info,
1804 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001805{
1806 struct listnode *node;
1807 struct audio_usecase *usecase;
1808 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301809 snd_device_t uc_derive_snd_device;
1810 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001811 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1812 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001813 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301814 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815 /*
1816 * This function is to make sure that all the usecases that are active on
1817 * the hardware codec backend are always routed to any one device that is
1818 * handled by the hardware codec.
1819 * For example, if low-latency and deep-buffer usecases are currently active
1820 * on speaker and out_set_parameters(headset) is received on low-latency
1821 * output, then we have to make sure deep-buffer is also switched to headset,
1822 * because of the limitation that both the devices cannot be enabled
1823 * at the same time as they share the same backend.
1824 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001825 /*
1826 * This call is to check if we need to force routing for a particular stream
1827 * If there is a backend configuration change for the device when a
1828 * new stream starts, then ADM needs to be closed and re-opened with the new
1829 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001830 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001831 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001832 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1833 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301834 /* For a2dp device reconfigure all active sessions
1835 * with new AFE encoder format based on a2dp state
1836 */
1837 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301838 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1839 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301840 audio_extn_a2dp_is_force_device_switch()) {
1841 force_routing = true;
1842 force_restart_session = true;
1843 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001844
1845 /*
1846 * Island cfg and power mode config needs to set before AFE port start.
1847 * Set force routing in case of voice device was enable before.
1848 */
1849 if (uc_info->type == VOICE_CALL &&
1850 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001851 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001852 platform_check_and_update_island_power_status(adev->platform,
1853 uc_info,
1854 snd_device)) {
1855 force_routing = true;
1856 ALOGD("%s:becf: force routing %d for power mode supported device",
1857 __func__, force_routing);
1858 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301859 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001862 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001863 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001864 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1865 switch_device[i] = false;
1866
1867 list_for_each(node, &adev->usecase_list) {
1868 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001869
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301870 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1871 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301872 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301873 platform_get_snd_device_name(usecase->out_snd_device),
1874 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301875 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1876 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301877 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1878 usecase, uc_info, snd_device);
1879 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001880 (is_codec_backend_out_device_type(&usecase->device_list) ||
1881 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1882 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1883 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1884 is_a2dp_out_device_type(&usecase->device_list) ||
1885 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301886 ((force_restart_session) ||
1887 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301888 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1889 __func__, use_case_table[usecase->id],
1890 platform_get_snd_device_name(usecase->out_snd_device));
1891 disable_audio_route(adev, usecase);
1892 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301893 /* Enable existing usecase on derived playback device */
1894 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301895 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301896 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001897 }
1898 }
1899
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301900 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1901 num_uc_to_switch);
1902
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001904 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301906 /* Make sure the previous devices to be disabled first and then enable the
1907 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001908 list_for_each(node, &adev->usecase_list) {
1909 usecase = node_to_item(node, struct audio_usecase, list);
1910 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001911 /* Check if output sound device to be switched can be split and if any
1912 of the split devices match with derived sound device */
1913 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1914 &num_devices, split_snd_devices) == 0) {
1915 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1916 for (i = 0; i < num_devices; i++) {
1917 /* Disable devices that do not match with derived sound device */
1918 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1919 disable_snd_device(adev, split_snd_devices[i]);
1920 }
1921 } else {
1922 disable_snd_device(adev, usecase->out_snd_device);
1923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 }
1925 }
1926
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001927 list_for_each(node, &adev->usecase_list) {
1928 usecase = node_to_item(node, struct audio_usecase, list);
1929 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001930 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1931 &num_devices, split_snd_devices) == 0) {
1932 /* Enable derived sound device only if it does not match with
1933 one of the split sound devices. This is because the matching
1934 sound device was not disabled */
1935 bool should_enable = true;
1936 for (i = 0; i < num_devices; i++) {
1937 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1938 should_enable = false;
1939 break;
1940 }
1941 }
1942 if (should_enable)
1943 enable_snd_device(adev, derive_snd_device[usecase->id]);
1944 } else {
1945 enable_snd_device(adev, derive_snd_device[usecase->id]);
1946 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001947 }
1948 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001950 /* Re-route all the usecases on the shared backend other than the
1951 specified usecase to new snd devices */
1952 list_for_each(node, &adev->usecase_list) {
1953 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301954 /* Update the out_snd_device only before enabling the audio route */
1955 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301956 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301957 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1958 use_case_table[usecase->id],
1959 platform_get_snd_device_name(usecase->out_snd_device));
1960 /* Update voc calibration before enabling Voice/VoIP route */
1961 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1962 status = platform_switch_voice_call_device_post(adev->platform,
1963 usecase->out_snd_device,
1964 platform_get_input_snd_device(
1965 adev->platform, NULL,
1966 &uc_info->device_list,
1967 usecase->type));
1968 enable_audio_route(adev, usecase);
1969 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1970 out_set_voip_volume(&usecase->stream.out->stream,
1971 usecase->stream.out->volume_l,
1972 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301973 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001974 }
1975 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976 }
1977}
1978
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301979static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001980 struct audio_usecase *uc_info,
1981 snd_device_t snd_device)
1982{
1983 struct listnode *node;
1984 struct audio_usecase *usecase;
1985 bool switch_device[AUDIO_USECASE_MAX];
1986 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001987 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001988 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001989
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301990 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1991 snd_device);
1992 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301993
1994 /*
1995 * Make sure out devices is checked against out codec backend device and
1996 * also in devices against in codec backend. Checking out device against in
1997 * codec backend or vice versa causes issues.
1998 */
1999 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002000 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002001
2002 /*
2003 * Island cfg and power mode config needs to set before AFE port start.
2004 * Set force routing in case of voice device was enable before.
2005 */
2006
2007 if (uc_info->type == VOICE_CALL &&
2008 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08002009 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002010 platform_check_and_update_island_power_status(adev->platform,
2011 uc_info,
2012 snd_device)) {
2013 force_routing = true;
2014 ALOGD("%s:becf: force routing %d for power mode supported device",
2015 __func__, force_routing);
2016 }
2017
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002018 /*
2019 * This function is to make sure that all the active capture usecases
2020 * are always routed to the same input sound device.
2021 * For example, if audio-record and voice-call usecases are currently
2022 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2023 * is received for voice call then we have to make sure that audio-record
2024 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2025 * because of the limitation that two devices cannot be enabled
2026 * at the same time if they share the same backend.
2027 */
2028 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2029 switch_device[i] = false;
2030
2031 list_for_each(node, &adev->usecase_list) {
2032 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302033 /*
2034 * TODO: Enhance below condition to handle BT sco/USB multi recording
2035 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302036
2037 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2038 (usecase->in_snd_device != snd_device || force_routing));
2039 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2040 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2041 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002042 ((backend_check_cond &&
2043 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002044 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002045 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002046 is_single_device_type_equal(&usecase->device_list,
2047 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002048 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002049 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002050 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302051 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002052 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002053 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002054 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002055 switch_device[usecase->id] = true;
2056 num_uc_to_switch++;
2057 }
2058 }
2059
2060 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002061 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002062
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302063 /* Make sure the previous devices to be disabled first and then enable the
2064 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002065 list_for_each(node, &adev->usecase_list) {
2066 usecase = node_to_item(node, struct audio_usecase, list);
2067 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002068 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002069 }
2070 }
2071
2072 list_for_each(node, &adev->usecase_list) {
2073 usecase = node_to_item(node, struct audio_usecase, list);
2074 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002075 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002076 }
2077 }
2078
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002079 /* Re-route all the usecases on the shared backend other than the
2080 specified usecase to new snd devices */
2081 list_for_each(node, &adev->usecase_list) {
2082 usecase = node_to_item(node, struct audio_usecase, list);
2083 /* Update the in_snd_device only before enabling the audio route */
2084 if (switch_device[usecase->id] ) {
2085 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302086 /* Update voc calibration before enabling Voice/VoIP route */
2087 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2088 snd_device_t voip_snd_device;
2089 voip_snd_device = platform_get_output_snd_device(adev->platform,
2090 usecase->stream.out,
2091 usecase->type);
2092 status = platform_switch_voice_call_device_post(adev->platform,
2093 voip_snd_device,
2094 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002095 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302096 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002097 }
2098 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002099 }
2100}
2101
Mingming Yin3a941d42016-02-17 18:08:05 -08002102static void reset_hdmi_sink_caps(struct stream_out *out) {
2103 int i = 0;
2104
2105 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2106 out->supported_channel_masks[i] = 0;
2107 }
2108 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2109 out->supported_formats[i] = 0;
2110 }
2111 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2112 out->supported_sample_rates[i] = 0;
2113 }
2114}
2115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002117static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118{
Mingming Yin3a941d42016-02-17 18:08:05 -08002119 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002120 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2121 out->extconn.cs.controller,
2122 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Mingming Yin3a941d42016-02-17 18:08:05 -08002124 reset_hdmi_sink_caps(out);
2125
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002126 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002127 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002128 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002129 out->extconn.cs.stream);
2130 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002131 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002132 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002133 }
2134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002137 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002138 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002139 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2140 case 6:
2141 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2142 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2143 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2144 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2145 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2146 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 break;
2148 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002149 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002150 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 break;
2152 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002153
2154 // check channel format caps
2155 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002156 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2157 out->extconn.cs.controller,
2158 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002159 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2160 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2161 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2162 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2163 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2164 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2165 }
2166
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002167 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2168 out->extconn.cs.controller,
2169 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002170 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2171 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2172 }
2173
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002174 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2175 out->extconn.cs.controller,
2176 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002177 ALOGV(":%s HDMI supports DTS format", __func__);
2178 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2179 }
2180
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002181 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2182 out->extconn.cs.controller,
2183 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002184 ALOGV(":%s HDMI supports DTS HD format", __func__);
2185 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2186 }
2187
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002188 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2189 out->extconn.cs.controller,
2190 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002191 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2192 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2193 }
2194
Mingming Yin3a941d42016-02-17 18:08:05 -08002195
2196 // check sample rate caps
2197 i = 0;
2198 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002199 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2200 out->extconn.cs.controller,
2201 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002202 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2203 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2204 }
2205 }
2206
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002207 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208}
2209
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002210static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2211 uint32_t *supported_sample_rates __unused,
2212 uint32_t max_rates __unused)
2213{
2214 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2215 supported_sample_rates,
2216 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302217 ssize_t i = 0;
2218
2219 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002220 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2221 supported_sample_rates[i]);
2222 }
2223 return count;
2224}
2225
2226static inline int read_usb_sup_channel_masks(bool is_playback,
2227 audio_channel_mask_t *supported_channel_masks,
2228 uint32_t max_masks)
2229{
2230 int channels = audio_extn_usb_get_max_channels(is_playback);
2231 int channel_count;
2232 uint32_t num_masks = 0;
2233 if (channels > MAX_HIFI_CHANNEL_COUNT)
2234 channels = MAX_HIFI_CHANNEL_COUNT;
2235
2236 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002237 // start from 2 channels as framework currently doesn't support mono.
2238 if (channels >= FCC_2) {
2239 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2240 }
2241 for (channel_count = FCC_2;
2242 channel_count <= channels && num_masks < max_masks;
2243 ++channel_count) {
2244 supported_channel_masks[num_masks++] =
2245 audio_channel_mask_for_index_assignment_from_count(channel_count);
2246 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002247 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002248 // For capture we report all supported channel masks from 1 channel up.
2249 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002250 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2251 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002252 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2253 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2254 if (channel_count <= FCC_2) {
2255 mask = audio_channel_in_mask_from_count(channel_count);
2256 supported_channel_masks[num_masks++] = mask;
2257 }
2258 const audio_channel_mask_t index_mask =
2259 audio_channel_mask_for_index_assignment_from_count(channel_count);
2260 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2261 supported_channel_masks[num_masks++] = index_mask;
2262 }
2263 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002264 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302265
vincenttewf51c94e2019-05-07 10:28:53 +08002266 for (size_t i = 0; i < num_masks; ++i) {
2267 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2268 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302269 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002270 return num_masks;
2271}
2272
2273static inline int read_usb_sup_formats(bool is_playback __unused,
2274 audio_format_t *supported_formats,
2275 uint32_t max_formats __unused)
2276{
2277 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2278 switch (bitwidth) {
2279 case 24:
2280 // XXX : usb.c returns 24 for s24 and s24_le?
2281 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2282 break;
2283 case 32:
2284 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2285 break;
2286 case 16:
2287 default :
2288 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2289 break;
2290 }
2291 ALOGV("%s: %s supported format %d", __func__,
2292 is_playback ? "P" : "C", bitwidth);
2293 return 1;
2294}
2295
2296static inline int read_usb_sup_params_and_compare(bool is_playback,
2297 audio_format_t *format,
2298 audio_format_t *supported_formats,
2299 uint32_t max_formats,
2300 audio_channel_mask_t *mask,
2301 audio_channel_mask_t *supported_channel_masks,
2302 uint32_t max_masks,
2303 uint32_t *rate,
2304 uint32_t *supported_sample_rates,
2305 uint32_t max_rates) {
2306 int ret = 0;
2307 int num_formats;
2308 int num_masks;
2309 int num_rates;
2310 int i;
2311
2312 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2313 max_formats);
2314 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2315 max_masks);
2316
2317 num_rates = read_usb_sup_sample_rates(is_playback,
2318 supported_sample_rates, max_rates);
2319
2320#define LUT(table, len, what, dflt) \
2321 for (i=0; i<len && (table[i] != what); i++); \
2322 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2323
2324 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2325 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2326 LUT(supported_sample_rates, num_rates, *rate, 0);
2327
2328#undef LUT
2329 return ret < 0 ? -EINVAL : 0; // HACK TBD
2330}
2331
Alexy Josephb1379942016-01-29 15:49:38 -08002332audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002333 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002334{
2335 struct audio_usecase *usecase;
2336 struct listnode *node;
2337
2338 list_for_each(node, &adev->usecase_list) {
2339 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002340 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002341 ALOGV("%s: usecase id %d", __func__, usecase->id);
2342 return usecase->id;
2343 }
2344 }
2345 return USECASE_INVALID;
2346}
2347
Alexy Josephb1379942016-01-29 15:49:38 -08002348struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002349 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002350{
2351 struct audio_usecase *usecase;
2352 struct listnode *node;
2353
2354 list_for_each(node, &adev->usecase_list) {
2355 usecase = node_to_item(node, struct audio_usecase, list);
2356 if (usecase->id == uc_id)
2357 return usecase;
2358 }
2359 return NULL;
2360}
2361
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302362/*
2363 * is a true native playback active
2364 */
2365bool audio_is_true_native_stream_active(struct audio_device *adev)
2366{
2367 bool active = false;
2368 int i = 0;
2369 struct listnode *node;
2370
2371 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2372 ALOGV("%s:napb: not in true mode or non hdphones device",
2373 __func__);
2374 active = false;
2375 goto exit;
2376 }
2377
2378 list_for_each(node, &adev->usecase_list) {
2379 struct audio_usecase *uc;
2380 uc = node_to_item(node, struct audio_usecase, list);
2381 struct stream_out *curr_out =
2382 (struct stream_out*) uc->stream.out;
2383
2384 if (curr_out && PCM_PLAYBACK == uc->type) {
2385 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2386 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2387 uc->id, curr_out->sample_rate,
2388 curr_out->bit_width,
2389 platform_get_snd_device_name(uc->out_snd_device));
2390
2391 if (is_offload_usecase(uc->id) &&
2392 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2393 active = true;
2394 ALOGD("%s:napb:native stream detected", __func__);
2395 }
2396 }
2397 }
2398exit:
2399 return active;
2400}
2401
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002402uint32_t adev_get_dsp_bit_width_enforce_mode()
2403{
2404 if (adev == NULL) {
2405 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2406 return 0;
2407 }
2408 return adev->dsp_bit_width_enforce_mode;
2409}
2410
2411static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2412{
2413 char value[PROPERTY_VALUE_MAX];
2414 int trial;
2415 uint32_t dsp_bit_width_enforce_mode = 0;
2416
2417 if (!mixer) {
2418 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2419 __func__);
2420 return 0;
2421 }
2422
2423 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2424 value, NULL) > 0) {
2425 trial = atoi(value);
2426 switch (trial) {
2427 case 16:
2428 dsp_bit_width_enforce_mode = 16;
2429 break;
2430 case 24:
2431 dsp_bit_width_enforce_mode = 24;
2432 break;
2433 case 32:
2434 dsp_bit_width_enforce_mode = 32;
2435 break;
2436 default:
2437 dsp_bit_width_enforce_mode = 0;
2438 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2439 break;
2440 }
2441 }
2442
2443 return dsp_bit_width_enforce_mode;
2444}
2445
2446static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2447 uint32_t enforce_mode,
2448 bool enable)
2449{
2450 struct mixer_ctl *ctl = NULL;
2451 const char *mixer_ctl_name = "ASM Bit Width";
2452 uint32_t asm_bit_width_mode = 0;
2453
2454 if (enforce_mode == 0) {
2455 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2456 return;
2457 }
2458
2459 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2460 if (!ctl) {
2461 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2462 __func__, mixer_ctl_name);
2463 return;
2464 }
2465
2466 if (enable)
2467 asm_bit_width_mode = enforce_mode;
2468 else
2469 asm_bit_width_mode = 0;
2470
2471 ALOGV("%s DSP bit width feature status is %d width=%d",
2472 __func__, enable, asm_bit_width_mode);
2473 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2474 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2475 asm_bit_width_mode);
2476
2477 return;
2478}
2479
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302480/*
2481 * if native DSD playback active
2482 */
2483bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2484{
2485 bool active = false;
2486 struct listnode *node = NULL;
2487 struct audio_usecase *uc = NULL;
2488 struct stream_out *curr_out = NULL;
2489
2490 list_for_each(node, &adev->usecase_list) {
2491 uc = node_to_item(node, struct audio_usecase, list);
2492 curr_out = (struct stream_out*) uc->stream.out;
2493
2494 if (curr_out && PCM_PLAYBACK == uc->type &&
2495 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2496 active = true;
2497 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302498 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302499 }
2500 }
2501 return active;
2502}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302503
2504static bool force_device_switch(struct audio_usecase *usecase)
2505{
2506 bool ret = false;
2507 bool is_it_true_mode = false;
2508
Zhou Song30f2c3e2018-02-08 14:02:15 +08002509 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302510 usecase->type == TRANSCODE_LOOPBACK_RX ||
2511 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002512 return false;
2513 }
2514
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002515 if(usecase->stream.out == NULL) {
2516 ALOGE("%s: stream.out is NULL", __func__);
2517 return false;
2518 }
2519
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302520 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002521 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002522 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2523 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302524 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2525 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2526 (!is_it_true_mode && adev->native_playback_enabled)){
2527 ret = true;
2528 ALOGD("napb: time to toggle native mode");
2529 }
2530 }
2531
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302532 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302533 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2534 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002535 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302536 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302537 ALOGD("Force a2dp device switch to update new encoder config");
2538 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002539 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302540
Florian Pfister1a84f312018-07-19 14:38:18 +02002541 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302542 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2543 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002544 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302545 return ret;
2546}
2547
Aalique Grahame22e49102018-12-18 14:23:57 -08002548static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2549{
2550 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2551}
2552
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302553bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2554{
2555 bool ret=false;
2556 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002557 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2558 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302559 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2560 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002561 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302562 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002563 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2564 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302565 ret = true;
2566
2567 return ret;
2568}
2569
2570bool is_a2dp_device(snd_device_t out_snd_device)
2571{
2572 bool ret=false;
2573 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2574 ret = true;
2575
2576 return ret;
2577}
2578
2579bool is_bt_soc_on(struct audio_device *adev)
2580{
2581 struct mixer_ctl *ctl;
2582 char *mixer_ctl_name = "BT SOC status";
2583 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2584 bool bt_soc_status = true;
2585 if (!ctl) {
2586 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2587 __func__, mixer_ctl_name);
2588 /*This is to ensure we dont break targets which dont have the kernel change*/
2589 return true;
2590 }
2591 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2592 ALOGD("BT SOC status: %d",bt_soc_status);
2593 return bt_soc_status;
2594}
2595
Zhou Song331c8e52019-08-26 14:16:12 +08002596static int configure_btsco_sample_rate(snd_device_t snd_device)
2597{
2598 struct mixer_ctl *ctl = NULL;
2599 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2600 char *rate_str = NULL;
2601 bool is_rx_dev = true;
2602
2603 if (is_btsco_device(snd_device, snd_device)) {
2604 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2605 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2606 if (!ctl_sr_tx || !ctl_sr_rx) {
2607 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2608 if (!ctl_sr)
2609 return -ENOSYS;
2610 }
2611
2612 switch (snd_device) {
2613 case SND_DEVICE_OUT_BT_SCO:
2614 rate_str = "KHZ_8";
2615 break;
2616 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2617 case SND_DEVICE_IN_BT_SCO_MIC:
2618 rate_str = "KHZ_8";
2619 is_rx_dev = false;
2620 break;
2621 case SND_DEVICE_OUT_BT_SCO_WB:
2622 rate_str = "KHZ_16";
2623 break;
2624 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2625 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2626 rate_str = "KHZ_16";
2627 is_rx_dev = false;
2628 break;
2629 default:
2630 return 0;
2631 }
2632
2633 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2634 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2635 return -ENOSYS;
2636 }
2637 return 0;
2638}
2639
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302640int out_standby_l(struct audio_stream *stream);
2641
Eric Laurent637e2d42018-11-15 12:24:31 -08002642struct stream_in *adev_get_active_input(const struct audio_device *adev)
2643{
2644 struct listnode *node;
2645 struct stream_in *last_active_in = NULL;
2646
2647 /* Get last added active input.
2648 * TODO: We may use a priority mechanism to pick highest priority active source */
2649 list_for_each(node, &adev->usecase_list)
2650 {
2651 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2652 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2653 last_active_in = usecase->stream.in;
2654 }
2655
2656 return last_active_in;
2657}
2658
2659struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2660{
2661 struct listnode *node;
2662
2663 /* First check active inputs with voice communication source and then
2664 * any input if audio mode is in communication */
2665 list_for_each(node, &adev->usecase_list)
2666 {
2667 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2668 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2669 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2670 return usecase->stream.in;
2671 }
2672 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2673 return adev_get_active_input(adev);
2674
2675 return NULL;
2676}
2677
Carter Hsu2e429db2019-05-14 18:50:52 +08002678/*
2679 * Aligned with policy.h
2680 */
2681static inline int source_priority(int inputSource)
2682{
2683 switch (inputSource) {
2684 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2685 return 9;
2686 case AUDIO_SOURCE_CAMCORDER:
2687 return 8;
2688 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2689 return 7;
2690 case AUDIO_SOURCE_UNPROCESSED:
2691 return 6;
2692 case AUDIO_SOURCE_MIC:
2693 return 5;
2694 case AUDIO_SOURCE_ECHO_REFERENCE:
2695 return 4;
2696 case AUDIO_SOURCE_FM_TUNER:
2697 return 3;
2698 case AUDIO_SOURCE_VOICE_RECOGNITION:
2699 return 2;
2700 case AUDIO_SOURCE_HOTWORD:
2701 return 1;
2702 default:
2703 break;
2704 }
2705 return 0;
2706}
2707
2708static struct stream_in *get_priority_input(struct audio_device *adev)
2709{
2710 struct listnode *node;
2711 struct audio_usecase *usecase;
2712 int last_priority = 0, priority;
2713 struct stream_in *priority_in = NULL;
2714 struct stream_in *in;
2715
2716 list_for_each(node, &adev->usecase_list) {
2717 usecase = node_to_item(node, struct audio_usecase, list);
2718 if (usecase->type == PCM_CAPTURE) {
2719 in = usecase->stream.in;
2720 if (!in)
2721 continue;
2722 priority = source_priority(in->source);
2723
2724 if (priority > last_priority) {
2725 last_priority = priority;
2726 priority_in = in;
2727 }
2728 }
2729 }
2730 return priority_in;
2731}
2732
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002733int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002735 snd_device_t out_snd_device = SND_DEVICE_NONE;
2736 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 struct audio_usecase *usecase = NULL;
2738 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002739 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002740 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302741 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002742 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002743 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302745 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2746
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002747 usecase = get_usecase_from_list(adev, uc_id);
2748 if (usecase == NULL) {
2749 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2750 return -EINVAL;
2751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002753 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002754 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002755 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002756 (usecase->type == ICC_CALL) ||
2757 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302758 if(usecase->stream.out == NULL) {
2759 ALOGE("%s: stream.out is NULL", __func__);
2760 return -EINVAL;
2761 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002762 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002763 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2764 uc_id);
2765 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2766 uc_id);
2767 } else {
2768 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302769 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002770 in_snd_device = platform_get_input_snd_device(adev->platform,
2771 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 &usecase->stream.out->device_list,
2773 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002774 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002775 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302776 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302777 if (usecase->stream.inout == NULL) {
2778 ALOGE("%s: stream.inout is NULL", __func__);
2779 return -EINVAL;
2780 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002781 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302782 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2783 stream_out.format = usecase->stream.inout->out_config.format;
2784 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302785 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002786 assign_devices(&usecase->device_list,
2787 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302788 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2789 if (usecase->stream.inout == NULL) {
2790 ALOGE("%s: stream.inout is NULL", __func__);
2791 return -EINVAL;
2792 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302793 struct listnode out_devices;
2794 list_init(&out_devices);
2795 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2796 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002797 assign_devices(&usecase->device_list,
2798 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002799 } else {
2800 /*
2801 * If the voice call is active, use the sound devices of voice call usecase
2802 * so that it would not result any device switch. All the usecases will
2803 * be switched to new device when select_devices() is called for voice call
2804 * usecase. This is to avoid switching devices for voice call when
2805 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002806 * choose voice call device only if the use case device is
2807 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002808 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002809 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002810 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002811 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002812 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2813 is_codec_backend_out_device_type(&usecase->device_list)) ||
2814 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2815 is_codec_backend_in_device_type(&usecase->device_list)) ||
2816 is_single_device_type_equal(&vc_usecase->device_list,
2817 AUDIO_DEVICE_OUT_HEARING_AID) ||
2818 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002819 AUDIO_DEVICE_IN_VOICE_CALL) ||
2820 (is_single_device_type_equal(&usecase->device_list,
2821 AUDIO_DEVICE_IN_USB_HEADSET) &&
2822 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302823 AUDIO_DEVICE_OUT_USB_HEADSET))||
2824 (is_single_device_type_equal(&usecase->device_list,
2825 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2826 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002827 in_snd_device = vc_usecase->in_snd_device;
2828 out_snd_device = vc_usecase->out_snd_device;
2829 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002830 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002831 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002832 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002833 if ((voip_usecase != NULL) &&
2834 (usecase->type == PCM_PLAYBACK) &&
2835 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002836 out_snd_device_backend_match = platform_check_backends_match(
2837 voip_usecase->out_snd_device,
2838 platform_get_output_snd_device(
2839 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302840 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002841 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002842 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2843 (is_codec_backend_out_device_type(&usecase->device_list) ||
2844 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002845 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002846 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002847 in_snd_device = voip_usecase->in_snd_device;
2848 out_snd_device = voip_usecase->out_snd_device;
2849 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002850 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002851 hfp_ucid = audio_extn_hfp_get_usecase();
2852 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002853 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002854 in_snd_device = hfp_usecase->in_snd_device;
2855 out_snd_device = hfp_usecase->out_snd_device;
2856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002857 }
2858 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302859 if (usecase->stream.out == NULL) {
2860 ALOGE("%s: stream.out is NULL", __func__);
2861 return -EINVAL;
2862 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002863 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002864 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002865 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002866 struct stream_out *voip_out = adev->primary_output;
2867 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002868 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002869 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2870 else
2871 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302872 usecase->stream.out,
2873 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002874 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002875
Eric Laurent637e2d42018-11-15 12:24:31 -08002876 if (voip_usecase)
2877 voip_out = voip_usecase->stream.out;
2878
2879 if (usecase->stream.out == voip_out && voip_in != NULL)
2880 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002882 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302883 if (usecase->stream.in == NULL) {
2884 ALOGE("%s: stream.in is NULL", __func__);
2885 return -EINVAL;
2886 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002887 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002888 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002889 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002890 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002891 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002892 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002893
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002894 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002895 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002896 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2897 USECASE_AUDIO_PLAYBACK_VOIP);
2898
Carter Hsu2e429db2019-05-14 18:50:52 +08002899 usecase->stream.in->enable_ec_port = false;
2900
Zhou Song62ea0282020-03-22 19:53:01 +08002901 bool is_ha_usecase = adev->ha_proxy_enable ?
2902 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2903 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2904 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002905 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002906 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002907 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002908 } else if (adev->primary_output &&
2909 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002910 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002911 } else {
2912 /* forcing speaker o/p device to get matching i/p pair
2913 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002914 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002915 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002916 priority_in = voip_in;
2917 } else {
2918 /* get the input with the highest priority source*/
2919 priority_in = get_priority_input(adev);
2920
Susan Wang727dd6b2021-03-26 11:28:59 -04002921 if (!priority_in ||
2922 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08002923 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002924 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002925 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2926 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2927 }
2928 else
2929 in_snd_device = platform_get_input_snd_device(adev->platform,
2930 priority_in,
2931 &out_devices,
2932 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002933 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002934 }
2935 }
2936
2937 if (out_snd_device == usecase->out_snd_device &&
2938 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302939
2940 if (!force_device_switch(usecase))
2941 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002944 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002945 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002946 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002947 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2948 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302949 }
2950
Aalique Grahame22e49102018-12-18 14:23:57 -08002951 if (out_snd_device != SND_DEVICE_NONE &&
2952 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2953 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2954 __func__,
2955 use_case_table[uc_id],
2956 adev->last_logged_snd_device[uc_id][0],
2957 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2958 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2959 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2960 -1,
2961 out_snd_device,
2962 platform_get_snd_device_name(out_snd_device),
2963 platform_get_snd_device_acdb_id(out_snd_device));
2964 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2965 }
2966 if (in_snd_device != SND_DEVICE_NONE &&
2967 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2968 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2969 __func__,
2970 use_case_table[uc_id],
2971 adev->last_logged_snd_device[uc_id][1],
2972 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2973 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2974 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2975 -1,
2976 in_snd_device,
2977 platform_get_snd_device_name(in_snd_device),
2978 platform_get_snd_device_acdb_id(in_snd_device));
2979 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2980 }
2981
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 /*
2984 * Limitation: While in call, to do a device switch we need to disable
2985 * and enable both RX and TX devices though one of them is same as current
2986 * device.
2987 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002988 if ((usecase->type == VOICE_CALL) &&
2989 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2990 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002991 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002992 }
2993
2994 if (((usecase->type == VOICE_CALL) ||
2995 (usecase->type == VOIP_CALL)) &&
2996 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2997 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302998 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002999 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07003000 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003001
3002 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303003 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003004 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003005 }
3006
Aalique Grahame22e49102018-12-18 14:23:57 -08003007 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
3008 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003009 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303010 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003011 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3012 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3013 else
3014 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303015 }
3016
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003017 /* Disable current sound devices */
3018 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003019 disable_audio_route(adev, usecase);
3020 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 }
3022
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003023 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003024 disable_audio_route(adev, usecase);
3025 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 }
3027
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003028 /* Applicable only on the targets that has external modem.
3029 * New device information should be sent to modem before enabling
3030 * the devices to reduce in-call device switch time.
3031 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003032 if ((usecase->type == VOICE_CALL) &&
3033 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3034 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003035 status = platform_switch_voice_call_enable_device_config(adev->platform,
3036 out_snd_device,
3037 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003038 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003039
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003040 /* Enable new sound devices */
3041 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003042 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303043 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303044 if (platform_check_codec_asrc_support(adev->platform))
3045 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003046 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003047 /* Enable haptics device for haptic usecase */
3048 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3049 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 }
3051
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003052 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303053 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003054 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003055 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003056
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303057 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003058 status = platform_switch_voice_call_device_post(adev->platform,
3059 out_snd_device,
3060 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003061
sangwoo170731f2013-06-08 15:36:36 +09003062 usecase->in_snd_device = in_snd_device;
3063 usecase->out_snd_device = out_snd_device;
3064
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303065 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3066 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303067 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003068 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003069 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003070 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3071 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3072 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3073 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3074 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3075 /*
3076 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3077 * configured device sample rate, if not update the COPP rate to be equal to the
3078 * device sample rate, else open COPP at stream sample rate
3079 */
3080 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3081 usecase->stream.out->sample_rate,
3082 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303083 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303084 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3085 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303086 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003087 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3088 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3089 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3090 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003091 }
3092 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003093
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303094 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3095 struct stream_in *voip_in = get_voice_communication_input(adev);
3096 struct audio_usecase *voip_in_usecase = NULL;
3097 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3098 if (voip_in != NULL &&
3099 voip_in_usecase != NULL &&
3100 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3101 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3102 (voip_in_usecase->in_snd_device ==
3103 platform_get_input_snd_device(adev->platform, voip_in,
3104 &usecase->stream.out->device_list,usecase->type))) {
3105 /*
3106 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3107 * for enabling echo-reference-voip with correct port
3108 */
3109 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3110 disable_audio_route(adev, voip_in_usecase);
3111 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3112 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3113 enable_audio_route(adev, voip_in_usecase);
3114 }
3115 }
3116
3117
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003118 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003119
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003120 /* If input stream is already running then effect needs to be
3121 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003122 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003123 check_and_enable_effect(adev);
3124
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003125 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003126 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303127 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003128 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3129
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003130 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303131 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003132 voice_extn_compress_voip_is_started(adev))
3133 voice_set_sidetone(adev, out_snd_device, true);
3134 }
3135
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003136 /* Applicable only on the targets that has external modem.
3137 * Enable device command should be sent to modem only after
3138 * enabling voice call mixer controls
3139 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003140 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003141 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3142 out_snd_device,
3143 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303144
3145 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003146 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303147 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003148 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303149 if (is_bt_soc_on(adev) == false){
3150 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003151 if (in->pcm != NULL)
3152 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303153 }
3154 }
3155 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3156 && usecase->stream.out->started) {
3157 if (is_bt_soc_on(adev) == false) {
3158 ALOGD("BT SCO/A2DP disconnected while in connection");
3159 out_standby_l(&usecase->stream.out->stream.common);
3160 }
3161 }
3162 } else if ((usecase->stream.out != NULL) &&
3163 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303164 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3165 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003166 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303167 usecase->stream.out->started) {
3168 if (is_bt_soc_on(adev) == false) {
3169 ALOGD("BT SCO/A2dp disconnected while in connection");
3170 out_standby_l(&usecase->stream.out->stream.common);
3171 }
3172 }
3173 }
3174
Yung Ti Su70cb8242018-06-22 17:38:47 +08003175 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003176 struct stream_out *voip_out = voip_usecase->stream.out;
3177 audio_extn_utils_send_app_type_gain(adev,
3178 voip_out->app_type_cfg.app_type,
3179 &voip_out->app_type_cfg.gain[0]);
3180 }
3181
Ajender Reddyb940b832021-07-07 11:51:42 +05303182 ALOGD("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 return status;
3185}
3186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187static int stop_input_stream(struct stream_in *in)
3188{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303189 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303191
3192 if (in == NULL) {
3193 ALOGE("%s: stream_in ptr is NULL", __func__);
3194 return -EINVAL;
3195 }
3196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003198 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Eric Laurent994a6932013-07-17 11:51:42 -07003200 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 uc_info = get_usecase_from_list(adev, in->usecase);
3203 if (uc_info == NULL) {
3204 ALOGE("%s: Could not find the usecase (%d) in the list",
3205 __func__, in->usecase);
3206 return -EINVAL;
3207 }
3208
Carter Hsu2e429db2019-05-14 18:50:52 +08003209 priority_in = get_priority_input(adev);
3210
Derek Chenea197282019-01-07 17:35:01 -08003211 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3212 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003213
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003214 /* Close in-call recording streams */
3215 voice_check_and_stop_incall_rec_usecase(adev, in);
3216
Eric Laurent150dbfe2013-02-27 14:31:02 -08003217 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003218 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003219
3220 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003221 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003223 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303224 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3225
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003226 list_remove(&uc_info->list);
3227 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228
Carter Hsu2e429db2019-05-14 18:50:52 +08003229 if (priority_in == in) {
3230 priority_in = get_priority_input(adev);
3231 if (priority_in)
3232 select_devices(adev, priority_in->usecase);
3233 }
3234
Vatsal Buchac09ae062018-11-14 13:25:08 +05303235 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003236 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 return ret;
3238}
3239
3240int start_input_stream(struct stream_in *in)
3241{
3242 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003243 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303245
3246 if (in == NULL) {
3247 ALOGE("%s: stream_in ptr is NULL", __func__);
3248 return -EINVAL;
3249 }
3250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003252 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003253 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254
Mingming Yin2664a5b2015-09-03 10:53:11 -07003255 if (get_usecase_from_list(adev, usecase) == NULL)
3256 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303257 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3258 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003259
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303260 if (CARD_STATUS_OFFLINE == in->card_status||
3261 CARD_STATUS_OFFLINE == adev->card_status) {
3262 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303263 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303264 goto error_config;
3265 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303266
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003267 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303268 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303269 ALOGE("%s: SCO profile is not ready, return error", __func__);
3270 ret = -EIO;
3271 goto error_config;
3272 }
3273 }
3274
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003275 /* Check if source matches incall recording usecase criteria */
3276 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3277 if (ret)
3278 goto error_config;
3279 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003280 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3281
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303282 if (audio_extn_cin_attached_usecase(in))
3283 audio_extn_cin_acquire_usecase(in);
3284
Mingming Yin2664a5b2015-09-03 10:53:11 -07003285 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3286 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3287 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003288 ret = -EINVAL;
3289 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003290 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003291
Eric Laurentb23d5282013-05-14 15:27:20 -07003292 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 if (in->pcm_device_id < 0) {
3294 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3295 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003296 ret = -EINVAL;
3297 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003301
3302 if (!uc_info) {
3303 ret = -ENOMEM;
3304 goto error_config;
3305 }
3306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 uc_info->id = in->usecase;
3308 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003309 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003310 list_init(&uc_info->device_list);
3311 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003312 uc_info->in_snd_device = SND_DEVICE_NONE;
3313 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003315 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003316 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303317 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3318 adev->perf_lock_opts,
3319 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003320 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321
Derek Chenea197282019-01-07 17:35:01 -08003322 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3323 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003324
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303325 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3326
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303327 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303328 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303329 if (ret)
3330 goto error_open;
3331 else
3332 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003333 }
3334
Haynes Mathew George16081042017-05-31 17:16:49 -07003335 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003336 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003337 ALOGE("%s: pcm stream not ready", __func__);
3338 goto error_open;
3339 }
3340 ret = pcm_start(in->pcm);
3341 if (ret < 0) {
3342 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3343 goto error_open;
3344 }
3345 } else {
3346 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3347 unsigned int pcm_open_retry_count = 0;
3348
Zhou Song62ea0282020-03-22 19:53:01 +08003349 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3350 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003351 flags |= PCM_MMAP | PCM_NOIRQ;
3352 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3353 } else if (in->realtime) {
3354 flags |= PCM_MMAP | PCM_NOIRQ;
3355 }
3356
Garmond Leunge2433c32017-09-28 21:51:22 -07003357 if (audio_extn_ffv_get_stream() == in) {
3358 ALOGD("%s: ffv stream, update pcm config", __func__);
3359 audio_extn_ffv_update_pcm_config(&config);
3360 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003361 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3362 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3363
3364 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003365 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003366 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003367 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003368 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303369 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303370 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3371 adev->card_status = CARD_STATUS_OFFLINE;
3372 in->card_status = CARD_STATUS_OFFLINE;
3373 ret = -EIO;
3374 goto error_open;
3375 }
3376
Haynes Mathew George16081042017-05-31 17:16:49 -07003377 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3378 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3379 if (in->pcm != NULL) {
3380 pcm_close(in->pcm);
3381 in->pcm = NULL;
3382 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003383 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003384 ret = -EIO;
3385 goto error_open;
3386 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003387 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003388 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3389 continue;
3390 }
3391 break;
3392 }
3393
3394 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003395 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003396 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003397 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003398 if (ret < 0) {
3399 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3400 pcm_close(in->pcm);
3401 in->pcm = NULL;
3402 goto error_open;
3403 }
3404 register_in_stream(in);
3405 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003406 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003407 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003408 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003409 if (ret < 0) {
3410 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003411 pcm_close(in->pcm);
3412 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003413 goto error_open;
3414 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003415 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003416 }
3417
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003418 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003419 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3420 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003421
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003422 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303423 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3424
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303425done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003426 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303427 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303428 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303429 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003430 return ret;
3431
3432error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003433 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303434 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003436
Eric Laurentc8400632013-02-14 19:04:54 -08003437error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003438 if (audio_extn_cin_attached_usecase(in))
3439 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303440 /*
3441 * sleep 50ms to allow sufficient time for kernel
3442 * drivers to recover incases like SSR.
3443 */
3444 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003445 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303446 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003447 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448}
3449
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003450void lock_input_stream(struct stream_in *in)
3451{
3452 pthread_mutex_lock(&in->pre_lock);
3453 pthread_mutex_lock(&in->lock);
3454 pthread_mutex_unlock(&in->pre_lock);
3455}
3456
3457void lock_output_stream(struct stream_out *out)
3458{
3459 pthread_mutex_lock(&out->pre_lock);
3460 pthread_mutex_lock(&out->lock);
3461 pthread_mutex_unlock(&out->pre_lock);
3462}
3463
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464/* must be called with out->lock locked */
3465static int send_offload_cmd_l(struct stream_out* out, int command)
3466{
3467 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3468
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003469 if (!cmd) {
3470 ALOGE("failed to allocate mem for command 0x%x", command);
3471 return -ENOMEM;
3472 }
3473
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 ALOGVV("%s %d", __func__, command);
3475
3476 cmd->cmd = command;
3477 list_add_tail(&out->offload_cmd_list, &cmd->node);
3478 pthread_cond_signal(&out->offload_cond);
3479 return 0;
3480}
3481
Gautam Manam14c198b2020-12-24 14:08:04 +05303482/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483static void stop_compressed_output_l(struct stream_out *out)
3484{
Gautam Manam14c198b2020-12-24 14:08:04 +05303485 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303487 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003490 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003491 if (out->compr != NULL) {
3492 compress_stop(out->compr);
3493 while (out->offload_thread_blocked) {
3494 pthread_cond_wait(&out->cond, &out->lock);
3495 }
3496 }
3497}
3498
Varun Balaraje49253e2017-07-06 19:48:56 +05303499bool is_interactive_usecase(audio_usecase_t uc_id)
3500{
3501 unsigned int i;
3502 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3503 if (uc_id == interactive_usecases[i])
3504 return true;
3505 }
3506 return false;
3507}
3508
3509static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3510{
3511 audio_usecase_t ret_uc = USECASE_INVALID;
3512 unsigned int intract_uc_index;
3513 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3514
3515 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3516 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3517 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3518 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3519 ret_uc = interactive_usecases[intract_uc_index];
3520 break;
3521 }
3522 }
3523
3524 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3525 return ret_uc;
3526}
3527
3528static void free_interactive_usecase(struct audio_device *adev,
3529 audio_usecase_t uc_id)
3530{
3531 unsigned int interact_uc_index;
3532 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3533
3534 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3535 if (interactive_usecases[interact_uc_index] == uc_id) {
3536 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3537 break;
3538 }
3539 }
3540 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3541}
3542
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003543bool is_offload_usecase(audio_usecase_t uc_id)
3544{
3545 unsigned int i;
3546 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3547 if (uc_id == offload_usecases[i])
3548 return true;
3549 }
3550 return false;
3551}
3552
Dhananjay Kumarac341582017-02-23 23:42:25 +05303553static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003554{
vivek mehta446c3962015-09-14 10:57:35 -07003555 audio_usecase_t ret_uc = USECASE_INVALID;
3556 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003557 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003558 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303559 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003560 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3561 else
3562 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003563
vivek mehta446c3962015-09-14 10:57:35 -07003564 pthread_mutex_lock(&adev->lock);
3565 if (get_usecase_from_list(adev, ret_uc) != NULL)
3566 ret_uc = USECASE_INVALID;
3567 pthread_mutex_unlock(&adev->lock);
3568
3569 return ret_uc;
3570 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003571
3572 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003573 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3574 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3575 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3576 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003577 break;
3578 }
3579 }
vivek mehta446c3962015-09-14 10:57:35 -07003580
3581 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3582 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003583}
3584
3585static void free_offload_usecase(struct audio_device *adev,
3586 audio_usecase_t uc_id)
3587{
vivek mehta446c3962015-09-14 10:57:35 -07003588 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003589 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003590
3591 if (!adev->multi_offload_enable)
3592 return;
3593
3594 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3595 if (offload_usecases[offload_uc_index] == uc_id) {
3596 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003597 break;
3598 }
3599 }
3600 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3601}
3602
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603static void *offload_thread_loop(void *context)
3604{
3605 struct stream_out *out = (struct stream_out *) context;
3606 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003607 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003610 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3612
3613 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003614 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003615 out->offload_state = OFFLOAD_STATE_IDLE;
3616 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003617 for (;;) {
3618 struct offload_cmd *cmd = NULL;
3619 stream_callback_event_t event;
3620 bool send_callback = false;
3621
3622 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3623 __func__, list_empty(&out->offload_cmd_list),
3624 out->offload_state);
3625 if (list_empty(&out->offload_cmd_list)) {
3626 ALOGV("%s SLEEPING", __func__);
3627 pthread_cond_wait(&out->offload_cond, &out->lock);
3628 ALOGV("%s RUNNING", __func__);
3629 continue;
3630 }
3631
3632 item = list_head(&out->offload_cmd_list);
3633 cmd = node_to_item(item, struct offload_cmd, node);
3634 list_remove(item);
3635
3636 ALOGVV("%s STATE %d CMD %d out->compr %p",
3637 __func__, out->offload_state, cmd->cmd, out->compr);
3638
3639 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3640 free(cmd);
3641 break;
3642 }
3643
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003644 // allow OFFLOAD_CMD_ERROR reporting during standby
3645 // this is needed to handle failures during compress_open
3646 // Note however that on a pause timeout, the stream is closed
3647 // and no offload usecase will be active. Therefore this
3648 // special case is needed for compress_open failures alone
3649 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3650 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003652 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003653 pthread_cond_signal(&out->cond);
3654 continue;
3655 }
3656 out->offload_thread_blocked = true;
3657 pthread_mutex_unlock(&out->lock);
3658 send_callback = false;
3659 switch(cmd->cmd) {
3660 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003661 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003663 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 send_callback = true;
3665 event = STREAM_CBK_EVENT_WRITE_READY;
3666 break;
3667 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003668 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303669 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003670 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303671 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003672 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303673 if (ret < 0)
3674 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303675 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303676 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003677 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003678 else
3679 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003680 if (-ENETRESET != ret && !(-EINTR == ret &&
3681 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303682 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303683 pthread_mutex_lock(&out->lock);
3684 out->send_new_metadata = 1;
3685 out->send_next_track_params = true;
3686 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303687 event = STREAM_CBK_EVENT_DRAIN_READY;
3688 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3689 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303690 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 break;
3692 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003693 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003694 ret = compress_drain(out->compr);
3695 ALOGD("copl(%p):out of compress_drain", out);
3696 // EINTR check avoids drain interruption due to SSR
3697 if (-ENETRESET != ret && !(-EINTR == ret &&
3698 CARD_STATUS_OFFLINE == out->card_status)) {
3699 send_callback = true;
3700 event = STREAM_CBK_EVENT_DRAIN_READY;
3701 } else
3702 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303704 case OFFLOAD_CMD_ERROR:
3705 ALOGD("copl(%p): sending error callback to AF", out);
3706 send_callback = true;
3707 event = STREAM_CBK_EVENT_ERROR;
3708 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003709 default:
3710 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3711 break;
3712 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003713 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003714 out->offload_thread_blocked = false;
3715 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003716 if (send_callback && out->client_callback) {
3717 ALOGVV("%s: sending client_callback event %d", __func__, event);
3718 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003719 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003720 free(cmd);
3721 }
3722
3723 pthread_cond_signal(&out->cond);
3724 while (!list_empty(&out->offload_cmd_list)) {
3725 item = list_head(&out->offload_cmd_list);
3726 list_remove(item);
3727 free(node_to_item(item, struct offload_cmd, node));
3728 }
3729 pthread_mutex_unlock(&out->lock);
3730
3731 return NULL;
3732}
3733
3734static int create_offload_callback_thread(struct stream_out *out)
3735{
3736 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3737 list_init(&out->offload_cmd_list);
3738 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3739 offload_thread_loop, out);
3740 return 0;
3741}
3742
3743static int destroy_offload_callback_thread(struct stream_out *out)
3744{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003745 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003746 stop_compressed_output_l(out);
3747 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3748
3749 pthread_mutex_unlock(&out->lock);
3750 pthread_join(out->offload_thread, (void **) NULL);
3751 pthread_cond_destroy(&out->offload_cond);
3752
3753 return 0;
3754}
3755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756static int stop_output_stream(struct stream_out *out)
3757{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303758 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 struct audio_usecase *uc_info;
3760 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003761 bool has_voip_usecase =
3762 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763
Eric Laurent994a6932013-07-17 11:51:42 -07003764 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003765 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 uc_info = get_usecase_from_list(adev, out->usecase);
3767 if (uc_info == NULL) {
3768 ALOGE("%s: Could not find the usecase (%d) in the list",
3769 __func__, out->usecase);
3770 return -EINVAL;
3771 }
3772
Zhou Songbaddf9f2020-11-20 13:57:39 +08003773 out->a2dp_muted = false;
3774
Derek Chenea197282019-01-07 17:35:01 -08003775 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3776 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003777
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003778 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303779 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003780 if (adev->visualizer_stop_output != NULL)
3781 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003782
3783 audio_extn_dts_remove_state_notifier_node(out->usecase);
3784
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003785 if (adev->offload_effects_stop_output != NULL)
3786 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003787 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3788 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3789 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003790 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003791
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003792 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3793 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003794 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003795 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003796
Eric Laurent150dbfe2013-02-27 14:31:02 -08003797 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003798 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003799
3800 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003801 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003802 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3803 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Aalique Grahame22e49102018-12-18 14:23:57 -08003805 audio_extn_extspk_update(adev->extspk);
3806
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003807 if (is_offload_usecase(out->usecase)) {
3808 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3809 adev->dsp_bit_width_enforce_mode,
3810 false);
3811 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003812 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003813 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3814 false);
3815
3816 if (ret != 0)
3817 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3818 /* default service interval was successfully updated,
3819 reopen USB backend with new service interval */
3820 ret = 0;
3821 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003822
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003823 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303824 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003825 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303826 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003827 ALOGV("Disable passthrough , reset mixer to pcm");
3828 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003829#ifdef AUDIO_GKI_ENABLED
3830 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3831 out->compr_config.codec->reserved[0] = 0;
3832#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003833 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003834#endif
Mingming Yin21854652016-04-13 11:54:02 -07003835 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003836 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3837 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003838
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303839 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003840 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303841 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303842
Manish Dewangan21a850a2017-08-14 12:03:55 +05303843 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003844 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3845 if (ret < 0)
3846 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3847 }
3848
Zhou Song642ec432020-12-23 16:11:10 +08003849 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003850 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003851 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003852 struct listnode *node;
3853 struct audio_usecase *usecase;
3854 list_for_each(node, &adev->usecase_list) {
3855 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003856 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3857 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303858 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003859 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003860 continue;
3861
3862 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3863 __func__, usecase->id, use_case_table[usecase->id],
3864 out->usecase, use_case_table[out->usecase]);
3865 select_devices(adev, usecase->id);
3866 }
3867 }
3868
Garmond Leung5fd0b552018-04-17 11:56:12 -07003869 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003870 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 return ret;
3872}
3873
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003874struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3875 unsigned int flags, unsigned int pcm_open_retry_count,
3876 struct pcm_config *config)
3877{
3878 struct pcm* pcm = NULL;
3879
3880 while (1) {
3881 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3882 if (pcm == NULL || !pcm_is_ready(pcm)) {
3883 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3884 if (pcm != NULL) {
3885 pcm_close(pcm);
3886 pcm = NULL;
3887 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003888 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003889 return NULL;
3890
Weiyin Jiang72197252019-10-09 11:49:32 +08003891 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003892 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3893 continue;
3894 }
3895 break;
3896 }
3897
3898 if (pcm_is_ready(pcm)) {
3899 int ret = pcm_prepare(pcm);
3900 if (ret < 0) {
3901 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3902 pcm_close(pcm);
3903 pcm = NULL;
3904 }
3905 }
3906
3907 return pcm;
3908}
3909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910int start_output_stream(struct stream_out *out)
3911{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 struct audio_usecase *uc_info;
3914 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003915 char mixer_ctl_name[128];
3916 struct mixer_ctl *ctl = NULL;
3917 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303918 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003919 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920
Haynes Mathew George380745d2017-10-04 15:27:45 -07003921 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003922 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3923 ret = -EINVAL;
3924 goto error_config;
3925 }
3926
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003927 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303928 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003929 get_device_types(&out->device_list), is_haptic_usecase);
3930
3931 bool is_speaker_active = compare_device_type(&out->device_list,
3932 AUDIO_DEVICE_OUT_SPEAKER);
3933 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3934 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303935
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303936 if (CARD_STATUS_OFFLINE == out->card_status ||
3937 CARD_STATUS_OFFLINE == adev->card_status) {
3938 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303939 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003940 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303941 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303942
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003943 //Update incall music usecase to reflect correct voice session
3944 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3945 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3946 if (ret != 0) {
3947 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3948 __func__, ret);
3949 goto error_config;
3950 }
3951 }
3952
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003953 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003954 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003955 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303956 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303957 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003958 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303959 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3960 ret = -EAGAIN;
3961 goto error_config;
3962 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303963 }
3964 }
3965 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003966 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303967 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003968 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303969 //combo usecase just by pass a2dp
3970 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003971 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303972 } else {
3973 ALOGE("%s: SCO profile is not ready, return error", __func__);
3974 ret = -EAGAIN;
3975 goto error_config;
3976 }
3977 }
3978 }
3979
Eric Laurentb23d5282013-05-14 15:27:20 -07003980 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981 if (out->pcm_device_id < 0) {
3982 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3983 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003984 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003985 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 }
3987
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003988 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003989 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3990 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003991 if (adev->haptic_pcm_device_id < 0) {
3992 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3993 __func__, adev->haptic_pcm_device_id, out->usecase);
3994 ret = -EINVAL;
3995 goto error_config;
3996 }
3997 }
3998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004000
4001 if (!uc_info) {
4002 ret = -ENOMEM;
4003 goto error_config;
4004 }
4005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006 uc_info->id = out->usecase;
4007 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004008 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004009 list_init(&uc_info->device_list);
4010 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004011 uc_info->in_snd_device = SND_DEVICE_NONE;
4012 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004013
4014 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004015 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004016 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4017 /* USB backend is not reopened immediately.
4018 This is eventually done as part of select_devices */
4019 }
4020
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004021 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022
Wei Wangf7ca6c92017-11-21 14:51:20 -08004023 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304024 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4025 adev->perf_lock_opts,
4026 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304027
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004028 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304029 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304030 if (audio_extn_passthru_is_enabled() &&
4031 audio_extn_passthru_is_passthrough_stream(out)) {
4032 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304033 }
4034 }
4035
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004036 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004037 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304038 if (!a2dp_combo) {
4039 check_a2dp_restore_l(adev, out, false);
4040 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004041 struct listnode dev;
4042 list_init(&dev);
4043 assign_devices(&dev, &out->device_list);
4044 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4045 reassign_device_list(&out->device_list,
4046 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004047 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004048 reassign_device_list(&out->device_list,
4049 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304050 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004051 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304052 }
4053 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304054 select_devices(adev, out->usecase);
4055 if (is_a2dp_out_device_type(&out->device_list) &&
4056 !adev->a2dp_started) {
4057 if (is_speaker_active || is_speaker_safe_active) {
4058 struct listnode dev;
4059 list_init(&dev);
4060 assign_devices(&dev, &out->device_list);
4061 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4062 reassign_device_list(&out->device_list,
4063 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4064 else
4065 reassign_device_list(&out->device_list,
4066 AUDIO_DEVICE_OUT_SPEAKER, "");
4067 select_devices(adev, out->usecase);
4068 assign_devices(&out->device_list, &dev);
4069 } else {
4070 ret = -EINVAL;
4071 goto error_open;
4072 }
4073 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304074 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004075
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004076 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4077 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004078 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004079 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004080
Derek Chenea197282019-01-07 17:35:01 -08004081 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4082 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004083
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004084 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4085 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004086
4087 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004088 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004089 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4090 ALOGE("%s: pcm stream not ready", __func__);
4091 goto error_open;
4092 }
4093 ret = pcm_start(out->pcm);
4094 if (ret < 0) {
4095 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4096 goto error_open;
4097 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004098 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004099 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004100 unsigned int flags = PCM_OUT;
4101 unsigned int pcm_open_retry_count = 0;
4102 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4103 flags |= PCM_MMAP | PCM_NOIRQ;
4104 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004105 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004106 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004107 } else
4108 flags |= PCM_MONOTONIC;
4109
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004110 if ((adev->vr_audio_mode_enabled) &&
4111 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4112 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4113 "PCM_Dev %d Topology", out->pcm_device_id);
4114 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4115 if (!ctl) {
4116 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4117 __func__, mixer_ctl_name);
4118 } else {
4119 //if success use ULLPP
4120 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4121 __func__, mixer_ctl_name, out->pcm_device_id);
4122 //There is a still a possibility that some sessions
4123 // that request for FAST|RAW when 3D audio is active
4124 //can go through ULLPP. Ideally we expects apps to
4125 //listen to audio focus and stop concurrent playback
4126 //Also, we will look for mode flag (voice_in_communication)
4127 //before enabling the realtime flag.
4128 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4129 }
4130 }
4131
Vatsal Bucha3f39f222021-06-29 16:16:55 +05304132 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4133 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304134
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004135 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4136 flags, pcm_open_retry_count,
4137 &(out->config));
4138 if (out->pcm == NULL) {
4139 ret = -EIO;
4140 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004141 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004142
4143 if (is_haptic_usecase) {
4144 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4145 adev->haptic_pcm_device_id,
4146 flags, pcm_open_retry_count,
4147 &(adev->haptics_config));
4148 // failure to open haptics pcm shouldnt stop audio,
4149 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004150
4151 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4152 ALOGD("%s: enable haptic audio synchronization", __func__);
4153 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4154 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004155 }
4156
Zhou Song2b8f28f2017-09-11 10:51:38 +08004157 // apply volume for voip playback after path is set up
4158 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4159 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304160 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4161 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304162 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4163 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004164 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4165 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304166 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004167 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004168 /*
4169 * set custom channel map if:
4170 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4171 * 2. custom channel map has been set by client
4172 * else default channel map of FC/FR/FL can always be set to DSP
4173 */
4174 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4175 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004176 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004177 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4178 adev->dsp_bit_width_enforce_mode,
4179 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004181 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004182 out->compr = compress_open(adev->snd_card,
4183 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004184 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004185 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304186 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304187 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4188 adev->card_status = CARD_STATUS_OFFLINE;
4189 out->card_status = CARD_STATUS_OFFLINE;
4190 ret = -EIO;
4191 goto error_open;
4192 }
4193
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004194 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004195 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004196 compress_close(out->compr);
4197 out->compr = NULL;
4198 ret = -EIO;
4199 goto error_open;
4200 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304201 /* compress_open sends params of the track, so reset the flag here */
4202 out->is_compr_metadata_avail = false;
4203
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004204 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004205 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004206
Fred Oh3f43e742015-03-04 18:42:34 -08004207 /* Since small bufs uses blocking writes, a write will be blocked
4208 for the default max poll time (20s) in the event of an SSR.
4209 Reduce the poll time to observe and deal with SSR faster.
4210 */
Ashish Jain5106d362016-05-11 19:23:33 +05304211 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004212 compress_set_max_poll_wait(out->compr, 1000);
4213 }
4214
Manish Dewangan69426c82017-01-30 17:35:36 +05304215 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304216 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304217
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004218 audio_extn_dts_create_state_notifier_node(out->usecase);
4219 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4220 popcount(out->channel_mask),
4221 out->playback_started);
4222
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004223#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304224 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004225 audio_extn_dolby_send_ddp_endp_params(adev);
4226#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304227 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4228 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004229 if (adev->visualizer_start_output != NULL)
4230 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4231 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304232 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004233 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004234 }
Derek Chenf13dd492018-11-13 14:53:51 -08004235
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004236 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004237 /* Update cached volume from media to offload/direct stream */
4238 struct listnode *node = NULL;
4239 list_for_each(node, &adev->active_outputs_list) {
4240 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4241 streams_output_ctxt_t,
4242 list);
4243 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4244 out->volume_l = out_ctxt->output->volume_l;
4245 out->volume_r = out_ctxt->output->volume_r;
4246 }
4247 }
4248 out_set_compr_volume(&out->stream,
4249 out->volume_l, out->volume_r);
4250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004252
4253 if (ret == 0) {
4254 register_out_stream(out);
4255 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004256 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4257 ALOGE("%s: pcm stream not ready", __func__);
4258 goto error_open;
4259 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004260 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004261 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004262 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004263 if (ret < 0)
4264 goto error_open;
4265 }
4266 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004267 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304268 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304269 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004270
vivek mehtad15d2bf2019-05-17 13:35:10 -07004271 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4272 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4273 audio_low_latency_hint_start();
4274 }
4275
Manish Dewangan21a850a2017-08-14 12:03:55 +05304276 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004277 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004278 if (ret < 0)
4279 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4280 }
4281
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004282 // consider a scenario where on pause lower layers are tear down.
4283 // so on resume, swap mixer control need to be sent only when
4284 // backend is active, hence rather than sending from enable device
4285 // sending it from start of streamtream
4286
4287 platform_set_swap_channels(adev, true);
4288
Haynes Mathew George380745d2017-10-04 15:27:45 -07004289 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304290 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004291 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004292error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004293 if (adev->haptic_pcm) {
4294 pcm_close(adev->haptic_pcm);
4295 adev->haptic_pcm = NULL;
4296 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004297 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304298 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004300error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304301 /*
4302 * sleep 50ms to allow sufficient time for kernel
4303 * drivers to recover incases like SSR.
4304 */
4305 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004306error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004307 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304308 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004309 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310}
4311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312static int check_input_parameters(uint32_t sample_rate,
4313 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004314 int channel_count,
4315 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004317 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304319 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4320 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4321 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004322 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004323 !audio_extn_compr_cap_format_supported(format) &&
4324 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004325 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004326
Aalique Grahame22e49102018-12-18 14:23:57 -08004327 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4328 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4329 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4330 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4331 return -EINVAL;
4332 }
4333
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004334 switch (channel_count) {
4335 case 1:
4336 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304337 case 3:
4338 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004339 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004340 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304341 case 10:
4342 case 12:
4343 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004344 break;
4345 default:
4346 ret = -EINVAL;
4347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348
4349 switch (sample_rate) {
4350 case 8000:
4351 case 11025:
4352 case 12000:
4353 case 16000:
4354 case 22050:
4355 case 24000:
4356 case 32000:
4357 case 44100:
4358 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004359 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304360 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004361 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304362 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 break;
4364 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004365 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366 }
4367
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004368 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369}
4370
Naresh Tanniru04f71882018-06-26 17:46:22 +05304371
4372/** Add a value in a list if not already present.
4373 * @return true if value was successfully inserted or already present,
4374 * false if the list is full and does not contain the value.
4375 */
4376static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4377 for (size_t i = 0; i < list_length; i++) {
4378 if (list[i] == value) return true; // value is already present
4379 if (list[i] == 0) { // no values in this slot
4380 list[i] = value;
4381 return true; // value inserted
4382 }
4383 }
4384 return false; // could not insert value
4385}
4386
4387/** Add channel_mask in supported_channel_masks if not already present.
4388 * @return true if channel_mask was successfully inserted or already present,
4389 * false if supported_channel_masks is full and does not contain channel_mask.
4390 */
4391static void register_channel_mask(audio_channel_mask_t channel_mask,
4392 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4393 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4394 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4395}
4396
4397/** Add format in supported_formats if not already present.
4398 * @return true if format was successfully inserted or already present,
4399 * false if supported_formats is full and does not contain format.
4400 */
4401static void register_format(audio_format_t format,
4402 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4403 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4404 "%s: stream can not declare supporting its format %x", __func__, format);
4405}
4406/** Add sample_rate in supported_sample_rates if not already present.
4407 * @return true if sample_rate was successfully inserted or already present,
4408 * false if supported_sample_rates is full and does not contain sample_rate.
4409 */
4410static void register_sample_rate(uint32_t sample_rate,
4411 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4412 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4413 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4414}
4415
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004416static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4417{
4418 uint32_t high = num1, low = num2, temp = 0;
4419
4420 if (!num1 || !num2)
4421 return 0;
4422
4423 if (num1 < num2) {
4424 high = num2;
4425 low = num1;
4426 }
4427
4428 while (low != 0) {
4429 temp = low;
4430 low = high % low;
4431 high = temp;
4432 }
4433 return (num1 * num2)/high;
4434}
4435
4436static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4437{
4438 uint32_t remainder = 0;
4439
4440 if (!multiplier)
4441 return num;
4442
4443 remainder = num % multiplier;
4444 if (remainder)
4445 num += (multiplier - remainder);
4446
4447 return num;
4448}
4449
Aalique Grahame22e49102018-12-18 14:23:57 -08004450static size_t get_stream_buffer_size(size_t duration_ms,
4451 uint32_t sample_rate,
4452 audio_format_t format,
4453 int channel_count,
4454 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455{
4456 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004457 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458
Aalique Grahame22e49102018-12-18 14:23:57 -08004459 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004460 if (is_low_latency)
4461 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304462
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004463 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004464 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465
Ralf Herzbd08d632018-09-28 15:50:49 +02004466 /* make sure the size is multiple of 32 bytes and additionally multiple of
4467 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004468 * At 48 kHz mono 16-bit PCM:
4469 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4470 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004471 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004472 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004473 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004474
4475 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476}
4477
Aalique Grahame22e49102018-12-18 14:23:57 -08004478static size_t get_input_buffer_size(uint32_t sample_rate,
4479 audio_format_t format,
4480 int channel_count,
4481 bool is_low_latency)
4482{
4483 /* Don't know if USB HIFI in this context so use true to be conservative */
4484 if (check_input_parameters(sample_rate, format, channel_count,
4485 true /*is_usb_hifi */) != 0)
4486 return 0;
4487
4488 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4489 sample_rate,
4490 format,
4491 channel_count,
4492 is_low_latency);
4493}
4494
Derek Chenf6318be2017-06-12 17:16:24 -04004495size_t get_output_period_size(uint32_t sample_rate,
4496 audio_format_t format,
4497 int channel_count,
4498 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304499{
4500 size_t size = 0;
4501 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4502
4503 if ((duration == 0) || (sample_rate == 0) ||
4504 (bytes_per_sample == 0) || (channel_count == 0)) {
4505 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4506 bytes_per_sample, channel_count);
4507 return -EINVAL;
4508 }
4509
4510 size = (sample_rate *
4511 duration *
4512 bytes_per_sample *
4513 channel_count) / 1000;
4514 /*
4515 * To have same PCM samples for all channels, the buffer size requires to
4516 * be multiple of (number of channels * bytes per sample)
4517 * For writes to succeed, the buffer must be written at address which is multiple of 32
4518 */
4519 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4520
4521 return (size/(channel_count * bytes_per_sample));
4522}
4523
Zhou Song48453a02018-01-10 17:50:59 +08004524static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304525{
4526 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004527 uint64_t written_frames = 0;
4528 uint64_t kernel_frames = 0;
4529 uint64_t dsp_frames = 0;
4530 uint64_t signed_frames = 0;
4531 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304532
4533 /* This adjustment accounts for buffering after app processor.
4534 * It is based on estimated DSP latency per use case, rather than exact.
4535 */
George Gao9ba8a142020-07-23 14:30:03 -07004536 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004537 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304538
Zhou Song48453a02018-01-10 17:50:59 +08004539 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004540 written_frames = out->written /
4541 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4542
Ashish Jain5106d362016-05-11 19:23:33 +05304543 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4544 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4545 * hence only estimate.
4546 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004547 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4548 kernel_frames = kernel_buffer_size /
4549 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304550
Weiyin Jiang4813da12020-05-28 00:37:28 +08004551 if (written_frames >= (kernel_frames + dsp_frames))
4552 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304553
Zhou Song48453a02018-01-10 17:50:59 +08004554 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304555 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004556 if (timestamp != NULL )
4557 *timestamp = out->writeAt;
4558 } else if (timestamp != NULL) {
4559 clock_gettime(CLOCK_MONOTONIC, timestamp);
4560 }
4561 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304562
Weiyin Jiang4813da12020-05-28 00:37:28 +08004563 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4564 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304565
4566 return actual_frames_rendered;
4567}
4568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4570{
4571 struct stream_out *out = (struct stream_out *)stream;
4572
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004573 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574}
4575
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004576static int out_set_sample_rate(struct audio_stream *stream __unused,
4577 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578{
4579 return -ENOSYS;
4580}
4581
4582static size_t out_get_buffer_size(const struct audio_stream *stream)
4583{
4584 struct stream_out *out = (struct stream_out *)stream;
4585
Varun Balaraje49253e2017-07-06 19:48:56 +05304586 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304587 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304588 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304589 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4590 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4591 else
4592 return out->compr_config.fragment_size;
4593 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004594 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304595 else if (is_offload_usecase(out->usecase) &&
4596 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304597 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004598
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004599 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004600 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601}
4602
4603static uint32_t out_get_channels(const struct audio_stream *stream)
4604{
4605 struct stream_out *out = (struct stream_out *)stream;
4606
4607 return out->channel_mask;
4608}
4609
4610static audio_format_t out_get_format(const struct audio_stream *stream)
4611{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004612 struct stream_out *out = (struct stream_out *)stream;
4613
4614 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615}
4616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004617static int out_set_format(struct audio_stream *stream __unused,
4618 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004619{
4620 return -ENOSYS;
4621}
4622
4623static int out_standby(struct audio_stream *stream)
4624{
4625 struct stream_out *out = (struct stream_out *)stream;
4626 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004627 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004628
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304629 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4630 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004632 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004634 if (adev->adm_deregister_stream)
4635 adev->adm_deregister_stream(adev->adm_data, out->handle);
4636
Weiyin Jiang280ea742020-09-08 20:28:22 +08004637 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004638 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004639 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004640
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004641 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004643 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4644 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304645 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004646 pthread_mutex_unlock(&adev->lock);
4647 pthread_mutex_unlock(&out->lock);
4648 ALOGD("VOIP output entered standby");
4649 return 0;
4650 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004651 if (out->pcm) {
4652 pcm_close(out->pcm);
4653 out->pcm = NULL;
4654 }
Meng Wanga09da002020-04-20 12:56:04 +08004655 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4656 if (adev->haptic_pcm) {
4657 pcm_close(adev->haptic_pcm);
4658 adev->haptic_pcm = NULL;
4659 }
4660
4661 if (adev->haptic_buffer != NULL) {
4662 free(adev->haptic_buffer);
4663 adev->haptic_buffer = NULL;
4664 adev->haptic_buffer_size = 0;
4665 }
4666 adev->haptic_pcm_device_id = 0;
4667 }
4668
Haynes Mathew George16081042017-05-31 17:16:49 -07004669 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4670 do_stop = out->playback_started;
4671 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004672
4673 if (out->mmap_shared_memory_fd >= 0) {
4674 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4675 __func__, out->mmap_shared_memory_fd);
4676 close(out->mmap_shared_memory_fd);
4677 out->mmap_shared_memory_fd = -1;
4678 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004679 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004680 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004681 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304682 out->send_next_track_params = false;
4683 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004684 out->gapless_mdata.encoder_delay = 0;
4685 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004686 if (out->compr != NULL) {
4687 compress_close(out->compr);
4688 out->compr = NULL;
4689 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004690 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004691 if (do_stop) {
4692 stop_output_stream(out);
4693 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304694 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004695 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004696 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 }
4698 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004699 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 return 0;
4701}
4702
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304703static int out_on_error(struct audio_stream *stream)
4704{
4705 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004706 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304707
4708 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004709 // always send CMD_ERROR for offload streams, this
4710 // is needed e.g. when SSR happens within compress_open
4711 // since the stream is active, offload_callback_thread is also active.
4712 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4713 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004714 }
4715 pthread_mutex_unlock(&out->lock);
4716
4717 status = out_standby(&out->stream.common);
4718
4719 lock_output_stream(out);
4720 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004721 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304722 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304723
4724 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4725 ALOGD("Setting previous card status if offline");
4726 out->prev_card_status_offline = true;
4727 }
4728
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304729 pthread_mutex_unlock(&out->lock);
4730
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004731 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304732}
4733
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304734/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004735 * standby implementation without locks, assumes that the callee already
4736 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304737 */
4738int out_standby_l(struct audio_stream *stream)
4739{
4740 struct stream_out *out = (struct stream_out *)stream;
4741 struct audio_device *adev = out->dev;
4742
4743 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4744 stream, out->usecase, use_case_table[out->usecase]);
4745
4746 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004747 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304748 if (adev->adm_deregister_stream)
4749 adev->adm_deregister_stream(adev->adm_data, out->handle);
4750
Weiyin Jiang280ea742020-09-08 20:28:22 +08004751 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304752 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004753 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304754
4755 out->standby = true;
4756 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4757 voice_extn_compress_voip_close_output_stream(stream);
4758 out->started = 0;
4759 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004760 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304761 return 0;
4762 } else if (!is_offload_usecase(out->usecase)) {
4763 if (out->pcm) {
4764 pcm_close(out->pcm);
4765 out->pcm = NULL;
4766 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004767 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4768 if (adev->haptic_pcm) {
4769 pcm_close(adev->haptic_pcm);
4770 adev->haptic_pcm = NULL;
4771 }
4772
4773 if (adev->haptic_buffer != NULL) {
4774 free(adev->haptic_buffer);
4775 adev->haptic_buffer = NULL;
4776 adev->haptic_buffer_size = 0;
4777 }
4778 adev->haptic_pcm_device_id = 0;
4779 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304780 } else {
4781 ALOGD("copl(%p):standby", out);
4782 out->send_next_track_params = false;
4783 out->is_compr_metadata_avail = false;
4784 out->gapless_mdata.encoder_delay = 0;
4785 out->gapless_mdata.encoder_padding = 0;
4786 if (out->compr != NULL) {
4787 compress_close(out->compr);
4788 out->compr = NULL;
4789 }
4790 }
4791 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004792 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304793 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004794 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304795 return 0;
4796}
4797
Aalique Grahame22e49102018-12-18 14:23:57 -08004798static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799{
Aalique Grahame22e49102018-12-18 14:23:57 -08004800 struct stream_out *out = (struct stream_out *)stream;
4801
4802 // We try to get the lock for consistency,
4803 // but it isn't necessary for these variables.
4804 // If we're not in standby, we may be blocked on a write.
4805 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4806 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4807 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4808
Andy Hunga1f48fa2019-07-01 18:14:53 -07004809 char buffer[256]; // for statistics formatting
4810 if (!is_offload_usecase(out->usecase)) {
4811 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4812 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4813 }
4814
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004815 if (out->start_latency_ms.n > 0) {
4816 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4817 dprintf(fd, " Start latency ms: %s\n", buffer);
4818 }
4819
Aalique Grahame22e49102018-12-18 14:23:57 -08004820 if (locked) {
4821 pthread_mutex_unlock(&out->lock);
4822 }
4823
4824 // dump error info
4825 (void)error_log_dump(
4826 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828 return 0;
4829}
4830
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004831static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4832{
4833 int ret = 0;
4834 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004835
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004836 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004837 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004838 return -EINVAL;
4839 }
4840
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304841 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004842
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4844 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304845 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004846 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004847 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4848 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304849 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004850 }
4851
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004852 ALOGV("%s new encoder delay %u and padding %u", __func__,
4853 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4854
4855 return 0;
4856}
4857
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004858static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4859{
4860 return out == adev->primary_output || out == adev->voice_tx_output;
4861}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004862
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304863// note: this call is safe only if the stream_cb is
4864// removed first in close_output_stream (as is done now).
4865static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4866{
4867 if (!stream || !parms)
4868 return;
4869
4870 struct stream_out *out = (struct stream_out *)stream;
4871 struct audio_device *adev = out->dev;
4872
4873 card_status_t status;
4874 int card;
4875 if (parse_snd_card_status(parms, &card, &status) < 0)
4876 return;
4877
4878 pthread_mutex_lock(&adev->lock);
4879 bool valid_cb = (card == adev->snd_card);
4880 pthread_mutex_unlock(&adev->lock);
4881
4882 if (!valid_cb)
4883 return;
4884
4885 lock_output_stream(out);
4886 if (out->card_status != status)
4887 out->card_status = status;
4888 pthread_mutex_unlock(&out->lock);
4889
4890 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4891 use_case_table[out->usecase],
4892 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4893
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304894 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304895 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304896 if (voice_is_call_state_active(adev) &&
4897 out == adev->primary_output) {
4898 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4899 pthread_mutex_lock(&adev->lock);
4900 voice_stop_call(adev);
4901 adev->mode = AUDIO_MODE_NORMAL;
4902 pthread_mutex_unlock(&adev->lock);
4903 }
4904 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304905 return;
4906}
4907
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004908int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004909 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004910{
4911 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004912 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004913 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004914 bool bypass_a2dp = false;
4915 bool reconfig = false;
4916 unsigned long service_interval = 0;
4917
4918 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004919 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4920
4921 list_init(&new_devices);
4922 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004923
4924 lock_output_stream(out);
4925 pthread_mutex_lock(&adev->lock);
4926
4927 /*
4928 * When HDMI cable is unplugged the music playback is paused and
4929 * the policy manager sends routing=0. But the audioflinger continues
4930 * to write data until standby time (3sec). As the HDMI core is
4931 * turned off, the write gets blocked.
4932 * Avoid this by routing audio to speaker until standby.
4933 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004934 if (is_single_device_type_equal(&out->device_list,
4935 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004936 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004937 !audio_extn_passthru_is_passthrough_stream(out) &&
4938 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004939 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004940 }
4941 /*
4942 * When A2DP is disconnected the
4943 * music playback is paused and the policy manager sends routing=0
4944 * But the audioflinger continues to write data until standby time
4945 * (3sec). As BT is turned off, the write gets blocked.
4946 * Avoid this by routing audio to speaker until standby.
4947 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004948 if (is_a2dp_out_device_type(&out->device_list) &&
4949 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004950 !audio_extn_a2dp_source_is_ready() &&
4951 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004952 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004953 }
4954 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08004955 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004956 * and the policy manager send routing=0. But if the USB is connected
4957 * back before the standby time, AFE is not closed and opened
4958 * when USB is connected back. So routing to speker will guarantee
4959 * AFE reconfiguration and AFE will be opend once USB is connected again
4960 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004961 if (is_usb_out_device_type(&out->device_list) &&
4962 list_empty(&new_devices) &&
4963 !audio_extn_usb_connected(NULL)) {
4964 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4965 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004966 /* To avoid a2dp to sco overlapping / BT device improper state
4967 * check with BT lib about a2dp streaming support before routing
4968 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004969 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004970 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004971 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4972 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004973 //combo usecase just by pass a2dp
4974 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4975 bypass_a2dp = true;
4976 } else {
4977 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4978 /* update device to a2dp and don't route as BT returned error
4979 * However it is still possible a2dp routing called because
4980 * of current active device disconnection (like wired headset)
4981 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004982 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004983 pthread_mutex_unlock(&adev->lock);
4984 pthread_mutex_unlock(&out->lock);
4985 goto error;
4986 }
4987 }
4988 }
4989
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004990 // Workaround: If routing to an non existing usb device, fail gracefully
4991 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004992 if (is_usb_out_device_type(&new_devices)) {
4993 struct str_parms *parms =
4994 str_parms_create_str(get_usb_device_address(&new_devices));
4995 if (!parms)
4996 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08004997 if (!audio_extn_usb_connected(NULL)) {
4998 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004999 pthread_mutex_unlock(&adev->lock);
5000 pthread_mutex_unlock(&out->lock);
5001 str_parms_destroy(parms);
5002 ret = -ENOSYS;
5003 goto error;
5004 }
5005 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005006 }
5007
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005008 // Workaround: If routing to an non existing hdmi device, fail gracefully
5009 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5010 (platform_get_edid_info_v2(adev->platform,
5011 out->extconn.cs.controller,
5012 out->extconn.cs.stream) != 0)) {
5013 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5014 pthread_mutex_unlock(&adev->lock);
5015 pthread_mutex_unlock(&out->lock);
5016 ret = -ENOSYS;
5017 goto error;
5018 }
5019
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005020 /*
5021 * select_devices() call below switches all the usecases on the same
5022 * backend to the new device. Refer to check_usecases_codec_backend() in
5023 * the select_devices(). But how do we undo this?
5024 *
5025 * For example, music playback is active on headset (deep-buffer usecase)
5026 * and if we go to ringtones and select a ringtone, low-latency usecase
5027 * will be started on headset+speaker. As we can't enable headset+speaker
5028 * and headset devices at the same time, select_devices() switches the music
5029 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5030 * So when the ringtone playback is completed, how do we undo the same?
5031 *
5032 * We are relying on the out_set_parameters() call on deep-buffer output,
5033 * once the ringtone playback is ended.
5034 * NOTE: We should not check if the current devices are same as new devices.
5035 * Because select_devices() must be called to switch back the music
5036 * playback to headset.
5037 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005038 if (!list_empty(&new_devices)) {
5039 bool same_dev = compare_devices(&out->device_list, &new_devices);
5040 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005041
5042 if (output_drives_call(adev, out)) {
5043 if (!voice_is_call_state_active(adev)) {
5044 if (adev->mode == AUDIO_MODE_IN_CALL) {
5045 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005046 ret = voice_start_call(adev);
5047 }
5048 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005049 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005050 adev->current_call_output = out;
5051 voice_update_devices_for_all_voice_usecases(adev);
5052 }
5053 }
5054
Mingshu Pang971ff702020-09-09 15:28:22 +08005055 if (is_usb_out_device_type(&out->device_list)) {
5056 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5057 audio_extn_usb_set_service_interval(true /*playback*/,
5058 service_interval,
5059 &reconfig);
5060 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5061 }
5062
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005063 if (!out->standby) {
5064 if (!same_dev) {
5065 ALOGV("update routing change");
5066 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5067 adev->perf_lock_opts,
5068 adev->perf_lock_opts_size);
5069 if (adev->adm_on_routing_change)
5070 adev->adm_on_routing_change(adev->adm_data,
5071 out->handle);
5072 }
5073 if (!bypass_a2dp) {
5074 select_devices(adev, out->usecase);
5075 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005076 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5077 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005078 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005079 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005080 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005081 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005082 }
5083
5084 if (!same_dev) {
5085 // on device switch force swap, lower functions will make sure
5086 // to check if swap is allowed or not.
5087 platform_set_swap_channels(adev, true);
5088 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5089 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005090 pthread_mutex_lock(&out->latch_lock);
5091 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5092 if (out->a2dp_muted) {
5093 out->a2dp_muted = false;
5094 if (is_offload_usecase(out->usecase))
5095 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5096 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5097 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005098 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005099 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005100 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5101 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5102 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005103 }
5104 }
5105
5106 pthread_mutex_unlock(&adev->lock);
5107 pthread_mutex_unlock(&out->lock);
5108
5109 /*handles device and call state changes*/
5110 audio_extn_extspk_update(adev->extspk);
5111
5112error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005113 ALOGV("%s: exit: code(%d)", __func__, ret);
5114 return ret;
5115}
5116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005117static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5118{
5119 struct stream_out *out = (struct stream_out *)stream;
5120 struct audio_device *adev = out->dev;
5121 struct str_parms *parms;
5122 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005123 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005124 int ext_controller = -1;
5125 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126
sangwoobc677242013-08-08 16:53:43 +09005127 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005128 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305130 if (!parms)
5131 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005132
5133 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5134 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005135 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005136 out->extconn.cs.controller = ext_controller;
5137 out->extconn.cs.stream = ext_stream;
5138 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5139 use_case_table[out->usecase], out->extconn.cs.controller,
5140 out->extconn.cs.stream);
5141 }
5142
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005143 if (out == adev->primary_output) {
5144 pthread_mutex_lock(&adev->lock);
5145 audio_extn_set_parameters(adev, parms);
5146 pthread_mutex_unlock(&adev->lock);
5147 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005148 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005149 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005150 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005151
5152 audio_extn_dts_create_state_notifier_node(out->usecase);
5153 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5154 popcount(out->channel_mask),
5155 out->playback_started);
5156
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005157 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005158 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005159
Surendar Karkaf51b5842018-04-26 11:28:38 +05305160 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5161 sizeof(value));
5162 if (err >= 0) {
5163 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5164 audio_extn_send_dual_mono_mixing_coefficients(out);
5165 }
5166
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305167 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5168 if (err >= 0) {
5169 strlcpy(out->profile, value, sizeof(out->profile));
5170 ALOGV("updating stream profile with value '%s'", out->profile);
5171 lock_output_stream(out);
5172 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5173 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005174 &out->device_list, out->flags,
5175 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305176 out->sample_rate, out->bit_width,
5177 out->channel_mask, out->profile,
5178 &out->app_type_cfg);
5179 pthread_mutex_unlock(&out->lock);
5180 }
5181
Alexy Joseph98988832017-01-13 14:56:59 -08005182 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005183 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5184 // and vendor.audio.hal.output.suspend.supported is set to true
5185 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005186 //check suspend parameter only for low latency and if the property
5187 //is enabled
5188 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5189 ALOGI("%s: got suspend_playback %s", __func__, value);
5190 lock_output_stream(out);
5191 if (!strncmp(value, "false", 5)) {
5192 //suspend_playback=false is supposed to set QOS value back to 75%
5193 //the mixer control sent with value Enable will achieve that
5194 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5195 } else if (!strncmp (value, "true", 4)) {
5196 //suspend_playback=true is supposed to remove QOS value
5197 //resetting the mixer control will set the default value
5198 //for the mixer control which is Disable and this removes the QOS vote
5199 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5200 } else {
5201 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5202 " got %s", __func__, value);
5203 ret = -1;
5204 }
5205
5206 if (ret != 0) {
5207 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5208 __func__, out->pm_qos_mixer_path, ret);
5209 }
5210
5211 pthread_mutex_unlock(&out->lock);
5212 }
5213 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005214
Alexy Joseph98988832017-01-13 14:56:59 -08005215 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305217error:
Eric Laurent994a6932013-07-17 11:51:42 -07005218 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005219 return ret;
5220}
5221
Paul McLeana50b7332018-12-17 08:24:21 -07005222static int in_set_microphone_direction(const struct audio_stream_in *stream,
5223 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005224 struct stream_in *in = (struct stream_in *)stream;
5225
5226 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5227
5228 in->direction = dir;
5229
5230 if (in->standby)
5231 return 0;
5232
5233 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005234}
5235
5236static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005237 struct stream_in *in = (struct stream_in *)stream;
5238
5239 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5240
5241 if (zoom > 1.0 || zoom < -1.0)
5242 return -EINVAL;
5243
5244 in->zoom = zoom;
5245
5246 if (in->standby)
5247 return 0;
5248
5249 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005250}
5251
5252
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005253static bool stream_get_parameter_channels(struct str_parms *query,
5254 struct str_parms *reply,
5255 audio_channel_mask_t *supported_channel_masks) {
5256 int ret = -1;
5257 char value[512];
5258 bool first = true;
5259 size_t i, j;
5260
5261 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5262 ret = 0;
5263 value[0] = '\0';
5264 i = 0;
5265 while (supported_channel_masks[i] != 0) {
5266 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5267 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5268 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305269 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005270
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305271 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005272 first = false;
5273 break;
5274 }
5275 }
5276 i++;
5277 }
5278 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5279 }
5280 return ret == 0;
5281}
5282
5283static bool stream_get_parameter_formats(struct str_parms *query,
5284 struct str_parms *reply,
5285 audio_format_t *supported_formats) {
5286 int ret = -1;
5287 char value[256];
5288 size_t i, j;
5289 bool first = true;
5290
5291 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5292 ret = 0;
5293 value[0] = '\0';
5294 i = 0;
5295 while (supported_formats[i] != 0) {
5296 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5297 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5298 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305299 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005300 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305301 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005302 first = false;
5303 break;
5304 }
5305 }
5306 i++;
5307 }
5308 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5309 }
5310 return ret == 0;
5311}
5312
5313static bool stream_get_parameter_rates(struct str_parms *query,
5314 struct str_parms *reply,
5315 uint32_t *supported_sample_rates) {
5316
5317 int i;
5318 char value[256];
5319 int ret = -1;
5320 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5321 ret = 0;
5322 value[0] = '\0';
5323 i=0;
5324 int cursor = 0;
5325 while (supported_sample_rates[i]) {
5326 int avail = sizeof(value) - cursor;
5327 ret = snprintf(value + cursor, avail, "%s%d",
5328 cursor > 0 ? "|" : "",
5329 supported_sample_rates[i]);
5330 if (ret < 0 || ret >= avail) {
5331 // if cursor is at the last element of the array
5332 // overwrite with \0 is duplicate work as
5333 // snprintf already put a \0 in place.
5334 // else
5335 // we had space to write the '|' at value[cursor]
5336 // (which will be overwritten) or no space to fill
5337 // the first element (=> cursor == 0)
5338 value[cursor] = '\0';
5339 break;
5340 }
5341 cursor += ret;
5342 ++i;
5343 }
5344 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5345 value);
5346 }
5347 return ret >= 0;
5348}
5349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005350static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5351{
5352 struct stream_out *out = (struct stream_out *)stream;
5353 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005354 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005355 char value[256];
5356 struct str_parms *reply = str_parms_create();
5357 size_t i, j;
5358 int ret;
5359 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005360
5361 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005362 if (reply) {
5363 str_parms_destroy(reply);
5364 }
5365 if (query) {
5366 str_parms_destroy(query);
5367 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005368 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5369 return NULL;
5370 }
5371
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005372 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5374 if (ret >= 0) {
5375 value[0] = '\0';
5376 i = 0;
5377 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005378 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5379 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005380 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005381 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005382 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005383 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 first = false;
5385 break;
5386 }
5387 }
5388 i++;
5389 }
5390 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5391 str = str_parms_to_str(reply);
5392 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005393 voice_extn_out_get_parameters(out, query, reply);
5394 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005396
Alexy Joseph62142aa2015-11-16 15:10:34 -08005397
5398 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5399 if (ret >= 0) {
5400 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305401 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5402 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005403 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305404 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005405 } else {
5406 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305407 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005408 }
5409 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005410 if (str)
5411 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005412 str = str_parms_to_str(reply);
5413 }
5414
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005415 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5416 if (ret >= 0) {
5417 value[0] = '\0';
5418 i = 0;
5419 first = true;
5420 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005421 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5422 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005423 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005424 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005425 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005426 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005427 first = false;
5428 break;
5429 }
5430 }
5431 i++;
5432 }
5433 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005434 if (str)
5435 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005436 str = str_parms_to_str(reply);
5437 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005438
5439 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5440 if (ret >= 0) {
5441 value[0] = '\0';
5442 i = 0;
5443 first = true;
5444 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005445 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5446 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005447 if (!first) {
5448 strlcat(value, "|", sizeof(value));
5449 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005450 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005451 first = false;
5452 break;
5453 }
5454 }
5455 i++;
5456 }
5457 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5458 if (str)
5459 free(str);
5460 str = str_parms_to_str(reply);
5461 }
5462
Alexy Joseph98988832017-01-13 14:56:59 -08005463 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5464 //only low latency track supports suspend_resume
5465 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005466 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005467 if (str)
5468 free(str);
5469 str = str_parms_to_str(reply);
5470 }
5471
5472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 str_parms_destroy(query);
5474 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005475 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 return str;
5477}
5478
5479static uint32_t out_get_latency(const struct audio_stream_out *stream)
5480{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005481 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005482 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005483 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005484
Alexy Josephaa54c872014-12-03 02:46:47 -08005485 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305486 lock_output_stream(out);
5487 latency = audio_extn_utils_compress_get_dsp_latency(out);
5488 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005489 } else if ((out->realtime) ||
5490 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005491 // since the buffer won't be filled up faster than realtime,
5492 // return a smaller number
5493 if (out->config.rate)
5494 period_ms = (out->af_period_multiplier * out->config.period_size *
5495 1000) / (out->config.rate);
5496 else
5497 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005498 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005499 } else {
5500 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005501 (out->config.rate);
5502 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)
5503 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005504 }
5505
Zhou Songd2537a02020-06-11 22:04:46 +08005506 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005507 latency += audio_extn_a2dp_get_encoder_latency();
5508
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305509 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005510 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511}
5512
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305513static float AmpToDb(float amplification)
5514{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305515 float db = DSD_VOLUME_MIN_DB;
5516 if (amplification > 0) {
5517 db = 20 * log10(amplification);
5518 if(db < DSD_VOLUME_MIN_DB)
5519 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305520 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305521 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305522}
5523
Arun Mirpuri5d170872019-03-26 13:21:31 -07005524static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5525 float right)
5526{
5527 struct stream_out *out = (struct stream_out *)stream;
5528 long volume = 0;
5529 char mixer_ctl_name[128] = "";
5530 struct audio_device *adev = out->dev;
5531 struct mixer_ctl *ctl = NULL;
5532 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5533 PCM_PLAYBACK);
5534
5535 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5536 "Playback %d Volume", pcm_device_id);
5537 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5538 if (!ctl) {
5539 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5540 __func__, mixer_ctl_name);
5541 return -EINVAL;
5542 }
5543 if (left != right)
5544 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5545 __func__, left, right);
5546 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5547 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5548 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5549 __func__, mixer_ctl_name, volume);
5550 return -EINVAL;
5551 }
5552 return 0;
5553}
5554
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305555static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5556 float right)
5557{
5558 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305559 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305560 char mixer_ctl_name[128];
5561 struct audio_device *adev = out->dev;
5562 struct mixer_ctl *ctl;
5563 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5564 PCM_PLAYBACK);
5565
5566 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5567 "Compress Playback %d Volume", pcm_device_id);
5568 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5569 if (!ctl) {
5570 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5571 __func__, mixer_ctl_name);
5572 return -EINVAL;
5573 }
5574 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5575 __func__, mixer_ctl_name, left, right);
5576 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5577 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5578 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5579
5580 return 0;
5581}
5582
Zhou Song2b8f28f2017-09-11 10:51:38 +08005583static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5584 float right)
5585{
5586 struct stream_out *out = (struct stream_out *)stream;
5587 char mixer_ctl_name[] = "App Type Gain";
5588 struct audio_device *adev = out->dev;
5589 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305590 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005591
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005592 if (!is_valid_volume(left, right)) {
5593 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5594 __func__, left, right);
5595 return -EINVAL;
5596 }
5597
Zhou Song2b8f28f2017-09-11 10:51:38 +08005598 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5599 if (!ctl) {
5600 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5601 __func__, mixer_ctl_name);
5602 return -EINVAL;
5603 }
5604
5605 set_values[0] = 0; //0: Rx Session 1:Tx Session
5606 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305607 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5608 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005609
5610 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5611 return 0;
5612}
5613
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305614static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5615 float right)
5616{
5617 struct stream_out *out = (struct stream_out *)stream;
5618 /* Volume control for pcm playback */
5619 if (left != right) {
5620 return -EINVAL;
5621 } else {
5622 char mixer_ctl_name[128];
5623 struct audio_device *adev = out->dev;
5624 struct mixer_ctl *ctl;
5625 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5626 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5627 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5628 if (!ctl) {
5629 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5630 return -EINVAL;
5631 }
5632
5633 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5634 int ret = mixer_ctl_set_value(ctl, 0, volume);
5635 if (ret < 0) {
5636 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5637 return -EINVAL;
5638 }
5639
5640 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5641
5642 return 0;
5643 }
5644}
5645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005646static int out_set_volume(struct audio_stream_out *stream, float left,
5647 float right)
5648{
Eric Laurenta9024de2013-04-04 09:19:12 -07005649 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005650 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305651 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005652
Arun Mirpuri5d170872019-03-26 13:21:31 -07005653 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005654 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5655 /* only take left channel into account: the API is for stereo anyway */
5656 out->muted = (left == 0.0f);
5657 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005658 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305659 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005660 /*
5661 * Set mute or umute on HDMI passthrough stream.
5662 * Only take left channel into account.
5663 * Mute is 0 and unmute 1
5664 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305665 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305666 } else if (out->format == AUDIO_FORMAT_DSD){
5667 char mixer_ctl_name[128] = "DSD Volume";
5668 struct audio_device *adev = out->dev;
5669 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5670
5671 if (!ctl) {
5672 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5673 __func__, mixer_ctl_name);
5674 return -EINVAL;
5675 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305676 volume[0] = (long)(AmpToDb(left));
5677 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305678 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5679 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005680 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005681 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005682 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5683 struct listnode *node = NULL;
5684 list_for_each(node, &adev->active_outputs_list) {
5685 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5686 streams_output_ctxt_t,
5687 list);
5688 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5689 out->volume_l = out_ctxt->output->volume_l;
5690 out->volume_r = out_ctxt->output->volume_r;
5691 }
5692 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005693 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005694 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005695 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5696 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005697 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005698 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005699 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005700 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005701 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5702 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305703 ret = out_set_compr_volume(stream, left, right);
5704 out->volume_l = left;
5705 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005706 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305707 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005708 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005709 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005710 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5711 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005712 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005713 if (!out->standby) {
5714 audio_extn_utils_send_app_type_gain(out->dev,
5715 out->app_type_cfg.app_type,
5716 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005717 if (!out->a2dp_muted)
5718 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005719 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005720 out->volume_l = left;
5721 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005722 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005723 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005724 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5725 ALOGV("%s: MMAP set volume called", __func__);
5726 if (!out->standby)
5727 ret = out_set_mmap_volume(stream, left, right);
5728 out->volume_l = left;
5729 out->volume_r = right;
5730 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305731 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305732 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5733 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005734 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305735 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005736 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305737 ret = out_set_pcm_volume(stream, left, right);
5738 else
5739 out->apply_volume = true;
5740
5741 out->volume_l = left;
5742 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005743 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305744 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005745 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5746 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005747 pthread_mutex_lock(&out->latch_lock);
5748 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005749 ret = out_set_pcm_volume(stream, left, right);
5750 out->volume_l = left;
5751 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005752 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005753 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005754 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005756 return -ENOSYS;
5757}
5758
Zhou Songc9672822017-08-16 16:01:39 +08005759static void update_frames_written(struct stream_out *out, size_t bytes)
5760{
5761 size_t bpf = 0;
5762
5763 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5764 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5765 bpf = 1;
5766 else if (!is_offload_usecase(out->usecase))
5767 bpf = audio_bytes_per_sample(out->format) *
5768 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005769
5770 pthread_mutex_lock(&out->position_query_lock);
5771 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005772 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005773 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5774 }
5775 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005776}
5777
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005778int split_and_write_audio_haptic_data(struct stream_out *out,
5779 const void *buffer, size_t bytes_to_write)
5780{
5781 struct audio_device *adev = out->dev;
5782
5783 int ret = 0;
5784 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5785 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5786 size_t frame_size = channel_count * bytes_per_sample;
5787 size_t frame_count = bytes_to_write / frame_size;
5788
5789 bool force_haptic_path =
5790 property_get_bool("vendor.audio.test_haptic", false);
5791
5792 // extract Haptics data from Audio buffer
5793 bool alloc_haptic_buffer = false;
5794 int haptic_channel_count = adev->haptics_config.channels;
5795 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5796 size_t audio_frame_size = frame_size - haptic_frame_size;
5797 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5798
5799 if (adev->haptic_buffer == NULL) {
5800 alloc_haptic_buffer = true;
5801 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5802 free(adev->haptic_buffer);
5803 adev->haptic_buffer_size = 0;
5804 alloc_haptic_buffer = true;
5805 }
5806
5807 if (alloc_haptic_buffer) {
5808 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005809 if(adev->haptic_buffer == NULL) {
5810 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5811 return -ENOMEM;
5812 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005813 adev->haptic_buffer_size = total_haptic_buffer_size;
5814 }
5815
5816 size_t src_index = 0, aud_index = 0, hap_index = 0;
5817 uint8_t *audio_buffer = (uint8_t *)buffer;
5818 uint8_t *haptic_buffer = adev->haptic_buffer;
5819
5820 // This is required for testing only. This works for stereo data only.
5821 // One channel is fed to audio stream and other to haptic stream for testing.
5822 if (force_haptic_path)
5823 audio_frame_size = haptic_frame_size = bytes_per_sample;
5824
5825 for (size_t i = 0; i < frame_count; i++) {
5826 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5827 audio_frame_size);
5828 aud_index += audio_frame_size;
5829 src_index += audio_frame_size;
5830
5831 if (adev->haptic_pcm)
5832 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5833 haptic_frame_size);
5834 hap_index += haptic_frame_size;
5835 src_index += haptic_frame_size;
5836
5837 // This is required for testing only.
5838 // Discard haptic channel data.
5839 if (force_haptic_path)
5840 src_index += haptic_frame_size;
5841 }
5842
5843 // write to audio pipeline
5844 ret = pcm_write(out->pcm, (void *)audio_buffer,
5845 frame_count * audio_frame_size);
5846
5847 // write to haptics pipeline
5848 if (adev->haptic_pcm)
5849 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5850 frame_count * haptic_frame_size);
5851
5852 return ret;
5853}
5854
Aalique Grahame22e49102018-12-18 14:23:57 -08005855#ifdef NO_AUDIO_OUT
5856static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5857 const void *buffer __unused, size_t bytes)
5858{
5859 struct stream_out *out = (struct stream_out *)stream;
5860
5861 /* No Output device supported other than BT for playback.
5862 * Sleep for the amount of buffer duration
5863 */
5864 lock_output_stream(out);
5865 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5866 (const struct audio_stream_out *)&out->stream) /
5867 out_get_sample_rate(&out->stream.common));
5868 pthread_mutex_unlock(&out->lock);
5869 return bytes;
5870}
5871#endif
5872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005873static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5874 size_t bytes)
5875{
5876 struct stream_out *out = (struct stream_out *)stream;
5877 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005878 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305879 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005880 const size_t frame_size = audio_stream_out_frame_size(stream);
5881 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305882 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005883 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005884
Haynes Mathew George380745d2017-10-04 15:27:45 -07005885 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005886 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305887
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305888 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005889
Dhananjay Kumarac341582017-02-23 23:42:25 +05305890 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305891 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305892 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5893 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005894 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305895 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305896 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305897 ALOGD(" %s: sound card is not active/SSR state", __func__);
5898 ret= -EIO;
5899 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305900 }
5901 }
5902
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305903 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305904 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305905 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305906 goto exit;
5907 }
5908
Haynes Mathew George16081042017-05-31 17:16:49 -07005909 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5910 ret = -EINVAL;
5911 goto exit;
5912 }
5913
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005914 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305915 !out->is_iec61937_info_available) {
5916
5917 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5918 out->is_iec61937_info_available = true;
5919 } else if (audio_extn_passthru_is_enabled()) {
5920 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305921 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305922
5923 if((out->format == AUDIO_FORMAT_DTS) ||
5924 (out->format == AUDIO_FORMAT_DTS_HD)) {
5925 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5926 buffer, bytes);
5927 if (ret) {
5928 if (ret != -ENOSYS) {
5929 out->is_iec61937_info_available = false;
5930 ALOGD("iec61937 transmission info not yet updated retry");
5931 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305932 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305933 /* if stream has started and after that there is
5934 * stream config change (iec transmission config)
5935 * then trigger select_device to update backend configuration.
5936 */
5937 out->stream_config_changed = true;
5938 pthread_mutex_lock(&adev->lock);
5939 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305940 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005941 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305942 ret = -EINVAL;
5943 goto exit;
5944 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305945 pthread_mutex_unlock(&adev->lock);
5946 out->stream_config_changed = false;
5947 out->is_iec61937_info_available = true;
5948 }
5949 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305950
Meng Wang4c32fb42020-01-16 17:57:11 +08005951#ifdef AUDIO_GKI_ENABLED
5952 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5953 compr_passthr = out->compr_config.codec->reserved[0];
5954#else
5955 compr_passthr = out->compr_config.codec->compr_passthr;
5956#endif
5957
Garmond Leung317cbf12017-09-13 16:20:50 -07005958 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005959 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305960 (out->is_iec61937_info_available == true)) {
5961 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5962 ret = -EINVAL;
5963 goto exit;
5964 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305965 }
5966 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305967
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005968 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005969 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005970 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5971 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005972 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305973 ret = -EIO;
5974 goto exit;
5975 }
5976 }
5977 }
5978
Weiyin Jiangabedea32020-12-09 12:49:19 +08005979 if (is_usb_out_device_type(&out->device_list) &&
5980 !audio_extn_usb_connected(NULL)) {
5981 ret = -EIO;
5982 goto exit;
5983 }
5984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005986 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005987 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5988
Eric Laurent150dbfe2013-02-27 14:31:02 -08005989 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005990 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5991 ret = voice_extn_compress_voip_start_output_stream(out);
5992 else
5993 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005994 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005995 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005996 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005997 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005998 goto exit;
5999 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306000 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006001 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006002
6003 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07006004 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006005 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306006 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006007 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006008 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306009
6010 if ((out->is_iec61937_info_available == true) &&
6011 (audio_extn_passthru_is_passthrough_stream(out))&&
6012 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6013 ret = -EINVAL;
6014 goto exit;
6015 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306016 if (out->set_dual_mono)
6017 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006018
6019 // log startup time in ms.
6020 simple_stats_log(
6021 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006022 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006023
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006024 if (adev->is_channel_status_set == false &&
6025 compare_device_type(&out->device_list,
6026 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006027 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306028 adev->is_channel_status_set = true;
6029 }
6030
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306031 if ((adev->use_old_pspd_mix_ctrl == true) &&
6032 (out->pspd_coeff_sent == false)) {
6033 /*
6034 * Need to resend pspd coefficients after stream started for
6035 * older kernel version as it does not save the coefficients
6036 * and also stream has to be started for coeff to apply.
6037 */
6038 usecase = get_usecase_from_list(adev, out->usecase);
6039 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306040 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306041 out->pspd_coeff_sent = true;
6042 }
6043 }
6044
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006045 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006046 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006047 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006048 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006049 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6050 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306051 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6052 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006053 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306054 out->send_next_track_params = false;
6055 out->is_compr_metadata_avail = false;
6056 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006057 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306058 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306059 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006060
Ashish Jain83a6cc22016-06-28 14:34:17 +05306061 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306062 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306063 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306064 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006065 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306066 return -EINVAL;
6067 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306068 audio_format_t dst_format = out->hal_op_format;
6069 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306070
Dieter Luecking5d57def2018-09-07 14:23:37 +02006071 /* prevent division-by-zero */
6072 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6073 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6074 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6075 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306076 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006077 ATRACE_END();
6078 return -EINVAL;
6079 }
6080
Ashish Jainf1eaa582016-05-23 20:54:24 +05306081 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6082 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6083
Ashish Jain83a6cc22016-06-28 14:34:17 +05306084 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306085 dst_format,
6086 buffer,
6087 src_format,
6088 frames);
6089
Ashish Jain83a6cc22016-06-28 14:34:17 +05306090 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306091 bytes_to_write);
6092
6093 /*Convert written bytes in audio flinger format*/
6094 if (ret > 0)
6095 ret = ((ret * format_to_bitwidth_table[out->format]) /
6096 format_to_bitwidth_table[dst_format]);
6097 }
6098 } else
6099 ret = compress_write(out->compr, buffer, bytes);
6100
Zhou Songc9672822017-08-16 16:01:39 +08006101 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6102 update_frames_written(out, bytes);
6103
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306104 if (ret < 0)
6105 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006106 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306107 /*msg to cb thread only if non blocking write is enabled*/
6108 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306109 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006110 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306111 } else if (-ENETRESET == ret) {
6112 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306113 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306114 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306115 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006116 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306117 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006118 }
Ashish Jain5106d362016-05-11 19:23:33 +05306119
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306120 /* Call compr start only when non-zero bytes of data is there to be rendered */
6121 if (!out->playback_started && ret > 0) {
6122 int status = compress_start(out->compr);
6123 if (status < 0) {
6124 ret = status;
6125 ALOGE("%s: compr start failed with err %d", __func__, errno);
6126 goto exit;
6127 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006128 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006129 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006130 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006131 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006132 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006133
6134 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6135 popcount(out->channel_mask),
6136 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006137 }
6138 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006139 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006140 return ret;
6141 } else {
6142 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006143 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006144 if (out->muted)
6145 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006146 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6147 __func__, frames, frame_size, bytes_to_write);
6148
Aalique Grahame22e49102018-12-18 14:23:57 -08006149 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006150 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6151 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6152 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006153 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6154 int16_t *src = (int16_t *)buffer;
6155 int16_t *dst = (int16_t *)buffer;
6156
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006157 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006158 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006159 "out_write called for %s use case with wrong properties",
6160 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006161
6162 /*
6163 * FIXME: this can be removed once audio flinger mixer supports
6164 * mono output
6165 */
6166
6167 /*
6168 * Code below goes over each frame in the buffer and adds both
6169 * L and R samples and then divides by 2 to convert to mono
6170 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006171 if (channel_count == 2) {
6172 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6173 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6174 }
6175 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006176 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006177 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006178
6179 // Note: since out_get_presentation_position() is called alternating with out_write()
6180 // by AudioFlinger, we can check underruns using the prior timestamp read.
6181 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6182 if (out->last_fifo_valid) {
6183 // compute drain to see if there is an underrun.
6184 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306185 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6186 int64_t frames_by_time =
6187 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6188 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006189 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6190
6191 if (underrun > 0) {
6192 simple_stats_log(&out->fifo_underruns, underrun);
6193
6194 ALOGW("%s: underrun(%lld) "
6195 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6196 __func__,
6197 (long long)out->fifo_underruns.n,
6198 (long long)frames_by_time,
6199 (long long)out->last_fifo_frames_remaining);
6200 }
6201 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6202 }
6203
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306204 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006205
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006206 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006207
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006208 if (out->config.rate)
6209 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6210 out->config.rate;
6211
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006212 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006213 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6214
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006215 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006216 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006217 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306218 out->convert_buffer != NULL) {
6219
6220 memcpy_by_audio_format(out->convert_buffer,
6221 out->hal_op_format,
6222 buffer,
6223 out->hal_ip_format,
6224 out->config.period_size * out->config.channels);
6225
6226 ret = pcm_write(out->pcm, out->convert_buffer,
6227 (out->config.period_size *
6228 out->config.channels *
6229 format_to_bitwidth_table[out->hal_op_format]));
6230 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306231 /*
6232 * To avoid underrun in DSP when the application is not pumping
6233 * data at required rate, check for the no. of bytes and ignore
6234 * pcm_write if it is less than actual buffer size.
6235 * It is a work around to a change in compress VOIP driver.
6236 */
6237 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6238 bytes < (out->config.period_size * out->config.channels *
6239 audio_bytes_per_sample(out->format))) {
6240 size_t voip_buf_size =
6241 out->config.period_size * out->config.channels *
6242 audio_bytes_per_sample(out->format);
6243 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6244 __func__, bytes, voip_buf_size);
6245 usleep(((uint64_t)voip_buf_size - bytes) *
6246 1000000 / audio_stream_out_frame_size(stream) /
6247 out_get_sample_rate(&out->stream.common));
6248 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006249 } else {
6250 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6251 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6252 else
6253 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6254 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306255 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006256
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006257 release_out_focus(out);
6258
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306259 if (ret < 0)
6260 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006261 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306262 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006264 }
6265
6266exit:
Zhou Songc9672822017-08-16 16:01:39 +08006267 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306268 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306269 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306270 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006271 pthread_mutex_unlock(&out->lock);
6272
6273 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006274 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006275 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306276 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306277 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306278 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306279 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306280 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306281 out->standby = true;
6282 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306283 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006284 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6285 /* prevent division-by-zero */
6286 uint32_t stream_size = audio_stream_out_frame_size(stream);
6287 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006288
Dieter Luecking5d57def2018-09-07 14:23:37 +02006289 if ((stream_size == 0) || (srate == 0)) {
6290 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6291 ATRACE_END();
6292 return -EINVAL;
6293 }
6294 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6295 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006296 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306297 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006298 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006299 return ret;
6300 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006301 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006302 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006303 return bytes;
6304}
6305
6306static int out_get_render_position(const struct audio_stream_out *stream,
6307 uint32_t *dsp_frames)
6308{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006309 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006310
6311 if (dsp_frames == NULL)
6312 return -EINVAL;
6313
6314 *dsp_frames = 0;
6315 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006316 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306317
6318 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6319 * this operation and adev_close_output_stream(where out gets reset).
6320 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306321 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006322 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306323 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006324 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306325 return 0;
6326 }
6327
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006328 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306329 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306330 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006331 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306332 if (ret < 0)
6333 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006334 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306335 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006336 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306337 if (-ENETRESET == ret) {
6338 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306339 out->card_status = CARD_STATUS_OFFLINE;
6340 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306341 } else if(ret < 0) {
6342 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306343 ret = -EINVAL;
6344 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306345 /*
6346 * Handle corner case where compress session is closed during SSR
6347 * and timestamp is queried
6348 */
6349 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306350 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306351 } else if (out->prev_card_status_offline) {
6352 ALOGE("ERROR: previously sound card was offline,return error");
6353 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306354 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306355 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006356 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306357 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306358 pthread_mutex_unlock(&out->lock);
6359 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006360 } else if (audio_is_linear_pcm(out->format)) {
6361 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006362 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006363 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006364 } else
6365 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006366}
6367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006368static int out_add_audio_effect(const struct audio_stream *stream __unused,
6369 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006370{
6371 return 0;
6372}
6373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006374static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6375 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006376{
6377 return 0;
6378}
6379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006380static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6381 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006382{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306383 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006384}
6385
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006386static int out_get_presentation_position(const struct audio_stream_out *stream,
6387 uint64_t *frames, struct timespec *timestamp)
6388{
6389 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306390 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006391 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006392
Ashish Jain5106d362016-05-11 19:23:33 +05306393 /* below piece of code is not guarded against any lock because audioFliner serializes
6394 * this operation and adev_close_output_stream( where out gets reset).
6395 */
6396 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306397 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006398 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306399 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6400 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6401 return 0;
6402 }
6403
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006404 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006405
Ashish Jain5106d362016-05-11 19:23:33 +05306406 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6407 ret = compress_get_tstamp(out->compr, &dsp_frames,
6408 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006409 // Adjustment accounts for A2dp encoder latency with offload usecases
6410 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006411 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006412 unsigned long offset =
6413 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6414 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6415 }
Ashish Jain5106d362016-05-11 19:23:33 +05306416 ALOGVV("%s rendered frames %ld sample_rate %d",
6417 __func__, dsp_frames, out->sample_rate);
6418 *frames = dsp_frames;
6419 if (ret < 0)
6420 ret = -errno;
6421 if (-ENETRESET == ret) {
6422 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306423 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306424 ret = -EINVAL;
6425 } else
6426 ret = 0;
6427 /* this is the best we can do */
6428 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006429 } else {
6430 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006431 unsigned int avail;
6432 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006433 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006434 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006435
Andy Hunga1f48fa2019-07-01 18:14:53 -07006436 if (out->kernel_buffer_size > avail) {
6437 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6438 } else {
6439 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6440 __func__, avail, out->kernel_buffer_size);
6441 avail = out->kernel_buffer_size;
6442 frames_temp = out->last_fifo_frames_remaining = 0;
6443 }
6444 out->last_fifo_valid = true;
6445 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6446
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006447 if (out->written >= frames_temp)
6448 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006449
Andy Hunga1f48fa2019-07-01 18:14:53 -07006450 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6451 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6452
Weiyin Jiangd4633762018-03-16 12:05:03 +08006453 // This adjustment accounts for buffering after app processor.
6454 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006455 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006456 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006457 if (signed_frames >= frames_temp)
6458 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006459
Weiyin Jiangd4633762018-03-16 12:05:03 +08006460 // Adjustment accounts for A2dp encoder latency with non offload usecases
6461 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006462 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006463 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6464 if (signed_frames >= frames_temp)
6465 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006466 }
6467
6468 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006469 *frames = signed_frames;
6470 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006471 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006472 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6473 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006474 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306475 *frames = out->written;
6476 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306477 if (is_offload_usecase(out->usecase))
6478 ret = -EINVAL;
6479 else
6480 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006481 }
6482 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006483 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006484 return ret;
6485}
6486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006487static int out_set_callback(struct audio_stream_out *stream,
6488 stream_callback_t callback, void *cookie)
6489{
6490 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006491 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006492
6493 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006494 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006495 out->client_callback = callback;
6496 out->client_cookie = cookie;
6497 if (out->adsp_hdlr_stream_handle) {
6498 ret = audio_extn_adsp_hdlr_stream_set_callback(
6499 out->adsp_hdlr_stream_handle,
6500 callback,
6501 cookie);
6502 if (ret)
6503 ALOGW("%s:adsp hdlr callback registration failed %d",
6504 __func__, ret);
6505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006506 pthread_mutex_unlock(&out->lock);
6507 return 0;
6508}
6509
6510static int out_pause(struct audio_stream_out* stream)
6511{
6512 struct stream_out *out = (struct stream_out *)stream;
6513 int status = -ENOSYS;
6514 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006515 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006516 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306517 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006518 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006519 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006520 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306521 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306522 status = compress_pause(out->compr);
6523
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006524 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006525
Mingming Yin21854652016-04-13 11:54:02 -07006526 if (audio_extn_passthru_is_active()) {
6527 ALOGV("offload use case, pause passthru");
6528 audio_extn_passthru_on_pause(out);
6529 }
6530
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306531 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006532 audio_extn_dts_notify_playback_state(out->usecase, 0,
6533 out->sample_rate, popcount(out->channel_mask),
6534 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006535 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006536 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006537 pthread_mutex_unlock(&out->lock);
6538 }
6539 return status;
6540}
6541
6542static int out_resume(struct audio_stream_out* stream)
6543{
6544 struct stream_out *out = (struct stream_out *)stream;
6545 int status = -ENOSYS;
6546 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006547 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006548 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306549 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006550 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006551 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006552 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306553 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306554 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006555 }
6556 if (!status) {
6557 out->offload_state = OFFLOAD_STATE_PLAYING;
6558 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306559 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006560 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6561 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006562 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006563 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006564 pthread_mutex_unlock(&out->lock);
6565 }
6566 return status;
6567}
6568
6569static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6570{
6571 struct stream_out *out = (struct stream_out *)stream;
6572 int status = -ENOSYS;
6573 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006574 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006575 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006576 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6577 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6578 else
6579 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6580 pthread_mutex_unlock(&out->lock);
6581 }
6582 return status;
6583}
6584
6585static int out_flush(struct audio_stream_out* stream)
6586{
6587 struct stream_out *out = (struct stream_out *)stream;
6588 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006589 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006590 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006591 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006592 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006593 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306594 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006595 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006596 } else {
6597 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306598 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006599 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006600 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006601 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006602 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006603 return 0;
6604 }
6605 return -ENOSYS;
6606}
6607
Haynes Mathew George16081042017-05-31 17:16:49 -07006608static int out_stop(const struct audio_stream_out* stream)
6609{
6610 struct stream_out *out = (struct stream_out *)stream;
6611 struct audio_device *adev = out->dev;
6612 int ret = -ENOSYS;
6613
6614 ALOGV("%s", __func__);
6615 pthread_mutex_lock(&adev->lock);
6616 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6617 out->playback_started && out->pcm != NULL) {
6618 pcm_stop(out->pcm);
6619 ret = stop_output_stream(out);
6620 out->playback_started = false;
6621 }
6622 pthread_mutex_unlock(&adev->lock);
6623 return ret;
6624}
6625
6626static int out_start(const struct audio_stream_out* stream)
6627{
6628 struct stream_out *out = (struct stream_out *)stream;
6629 struct audio_device *adev = out->dev;
6630 int ret = -ENOSYS;
6631
6632 ALOGV("%s", __func__);
6633 pthread_mutex_lock(&adev->lock);
6634 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6635 !out->playback_started && out->pcm != NULL) {
6636 ret = start_output_stream(out);
6637 if (ret == 0) {
6638 out->playback_started = true;
6639 }
6640 }
6641 pthread_mutex_unlock(&adev->lock);
6642 return ret;
6643}
6644
6645/*
6646 * Modify config->period_count based on min_size_frames
6647 */
6648static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6649{
6650 int periodCountRequested = (min_size_frames + config->period_size - 1)
6651 / config->period_size;
6652 int periodCount = MMAP_PERIOD_COUNT_MIN;
6653
6654 ALOGV("%s original config.period_size = %d config.period_count = %d",
6655 __func__, config->period_size, config->period_count);
6656
6657 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6658 periodCount *= 2;
6659 }
6660 config->period_count = periodCount;
6661
6662 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6663}
6664
Phil Burkfe17efd2019-03-25 10:23:35 -07006665// Read offset for the positional timestamp from a persistent vendor property.
6666// This is to workaround apparent inaccuracies in the timing information that
6667// is used by the AAudio timing model. The inaccuracies can cause glitches.
6668static int64_t get_mmap_out_time_offset() {
6669 const int32_t kDefaultOffsetMicros = 0;
6670 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006671 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006672 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6673 return mmap_time_offset_micros * (int64_t)1000;
6674}
6675
Haynes Mathew George16081042017-05-31 17:16:49 -07006676static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6677 int32_t min_size_frames,
6678 struct audio_mmap_buffer_info *info)
6679{
6680 struct stream_out *out = (struct stream_out *)stream;
6681 struct audio_device *adev = out->dev;
6682 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006683 unsigned int offset1 = 0;
6684 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006685 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006686 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006687 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006688
Arun Mirpuri5d170872019-03-26 13:21:31 -07006689 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306690 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006691 pthread_mutex_lock(&adev->lock);
6692
Sharad Sanglec6f32552018-05-04 16:15:38 +05306693 if (CARD_STATUS_OFFLINE == out->card_status ||
6694 CARD_STATUS_OFFLINE == adev->card_status) {
6695 ALOGW("out->card_status or adev->card_status offline, try again");
6696 ret = -EIO;
6697 goto exit;
6698 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306699 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006700 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6701 ret = -EINVAL;
6702 goto exit;
6703 }
6704 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6705 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6706 ret = -ENOSYS;
6707 goto exit;
6708 }
6709 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6710 if (out->pcm_device_id < 0) {
6711 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6712 __func__, out->pcm_device_id, out->usecase);
6713 ret = -EINVAL;
6714 goto exit;
6715 }
6716
6717 adjust_mmap_period_count(&out->config, min_size_frames);
6718
Arun Mirpuri5d170872019-03-26 13:21:31 -07006719 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006720 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6721 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6722 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306723 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306724 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6725 out->card_status = CARD_STATUS_OFFLINE;
6726 adev->card_status = CARD_STATUS_OFFLINE;
6727 ret = -EIO;
6728 goto exit;
6729 }
6730
Haynes Mathew George16081042017-05-31 17:16:49 -07006731 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6732 step = "open";
6733 ret = -ENODEV;
6734 goto exit;
6735 }
6736 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6737 if (ret < 0) {
6738 step = "begin";
6739 goto exit;
6740 }
juyuchen626833d2019-06-04 16:48:02 +08006741
6742 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006743 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006744 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006745 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006746 ret = platform_get_mmap_data_fd(adev->platform,
6747 out->pcm_device_id, 0 /*playback*/,
6748 &info->shared_memory_fd,
6749 &mmap_size);
6750 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006751 // Fall back to non exclusive mode
6752 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6753 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006754 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6755 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6756
Arun Mirpuri5d170872019-03-26 13:21:31 -07006757 if (mmap_size < buffer_size) {
6758 step = "mmap";
6759 goto exit;
6760 }
juyuchen626833d2019-06-04 16:48:02 +08006761 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006762 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006763 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006764 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006765
6766 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6767 if (ret < 0) {
6768 step = "commit";
6769 goto exit;
6770 }
6771
Phil Burkfe17efd2019-03-25 10:23:35 -07006772 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6773
Haynes Mathew George16081042017-05-31 17:16:49 -07006774 out->standby = false;
6775 ret = 0;
6776
Arun Mirpuri5d170872019-03-26 13:21:31 -07006777 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006778 __func__, info->shared_memory_address, info->buffer_size_frames);
6779
6780exit:
6781 if (ret != 0) {
6782 if (out->pcm == NULL) {
6783 ALOGE("%s: %s - %d", __func__, step, ret);
6784 } else {
6785 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6786 pcm_close(out->pcm);
6787 out->pcm = NULL;
6788 }
6789 }
6790 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306791 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006792 return ret;
6793}
6794
6795static int out_get_mmap_position(const struct audio_stream_out *stream,
6796 struct audio_mmap_position *position)
6797{
6798 struct stream_out *out = (struct stream_out *)stream;
6799 ALOGVV("%s", __func__);
6800 if (position == NULL) {
6801 return -EINVAL;
6802 }
6803 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006804 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006805 return -ENOSYS;
6806 }
6807 if (out->pcm == NULL) {
6808 return -ENOSYS;
6809 }
6810
6811 struct timespec ts = { 0, 0 };
6812 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6813 if (ret < 0) {
6814 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6815 return ret;
6816 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006817 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6818 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006819 return 0;
6820}
6821
6822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006823/** audio_stream_in implementation **/
6824static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6825{
6826 struct stream_in *in = (struct stream_in *)stream;
6827
6828 return in->config.rate;
6829}
6830
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006831static int in_set_sample_rate(struct audio_stream *stream __unused,
6832 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006833{
6834 return -ENOSYS;
6835}
6836
6837static size_t in_get_buffer_size(const struct audio_stream *stream)
6838{
6839 struct stream_in *in = (struct stream_in *)stream;
6840
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006841 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6842 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006843 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6844 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306845 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306846 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006847
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006848 return in->config.period_size * in->af_period_multiplier *
6849 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006850}
6851
6852static uint32_t in_get_channels(const struct audio_stream *stream)
6853{
6854 struct stream_in *in = (struct stream_in *)stream;
6855
6856 return in->channel_mask;
6857}
6858
6859static audio_format_t in_get_format(const struct audio_stream *stream)
6860{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006861 struct stream_in *in = (struct stream_in *)stream;
6862
6863 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006864}
6865
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006866static int in_set_format(struct audio_stream *stream __unused,
6867 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868{
6869 return -ENOSYS;
6870}
6871
6872static int in_standby(struct audio_stream *stream)
6873{
6874 struct stream_in *in = (struct stream_in *)stream;
6875 struct audio_device *adev = in->dev;
6876 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306877 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6878 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006879 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306880
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006881 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006882 if (!in->standby && in->is_st_session) {
6883 ALOGD("%s: sound trigger pcm stop lab", __func__);
6884 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006885 if (adev->num_va_sessions > 0)
6886 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006887 in->standby = 1;
6888 }
6889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006890 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006891 if (adev->adm_deregister_stream)
6892 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6893
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006894 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006895 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006896 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006897 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006898 voice_extn_compress_voip_close_input_stream(stream);
6899 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006900 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6901 do_stop = in->capture_started;
6902 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006903 if (in->mmap_shared_memory_fd >= 0) {
6904 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6905 __func__, in->mmap_shared_memory_fd);
6906 close(in->mmap_shared_memory_fd);
6907 in->mmap_shared_memory_fd = -1;
6908 }
Zhou Songa8895042016-07-05 17:54:22 +08006909 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306910 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306911 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006912 }
6913
Arun Mirpuri5d170872019-03-26 13:21:31 -07006914 if (in->pcm) {
6915 ATRACE_BEGIN("pcm_in_close");
6916 pcm_close(in->pcm);
6917 ATRACE_END();
6918 in->pcm = NULL;
6919 }
6920
Carter Hsu2e429db2019-05-14 18:50:52 +08006921 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006922 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006923
George Gao3018ede2019-10-23 13:23:00 -07006924 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6925 if (adev->num_va_sessions > 0)
6926 adev->num_va_sessions--;
6927 }
Quinn Malef6050362019-01-30 15:55:40 -08006928
Eric Laurent150dbfe2013-02-27 14:31:02 -08006929 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006930 }
6931 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006932 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006933 return status;
6934}
6935
Aalique Grahame22e49102018-12-18 14:23:57 -08006936static int in_dump(const struct audio_stream *stream,
6937 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006938{
Aalique Grahame22e49102018-12-18 14:23:57 -08006939 struct stream_in *in = (struct stream_in *)stream;
6940
6941 // We try to get the lock for consistency,
6942 // but it isn't necessary for these variables.
6943 // If we're not in standby, we may be blocked on a read.
6944 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6945 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6946 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6947 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6948
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006949 char buffer[256]; // for statistics formatting
6950 if (in->start_latency_ms.n > 0) {
6951 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6952 dprintf(fd, " Start latency ms: %s\n", buffer);
6953 }
6954
Aalique Grahame22e49102018-12-18 14:23:57 -08006955 if (locked) {
6956 pthread_mutex_unlock(&in->lock);
6957 }
6958
6959 // dump error info
6960 (void)error_log_dump(
6961 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006963 return 0;
6964}
6965
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306966static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6967{
6968 if (!stream || !parms)
6969 return;
6970
6971 struct stream_in *in = (struct stream_in *)stream;
6972 struct audio_device *adev = in->dev;
6973
6974 card_status_t status;
6975 int card;
6976 if (parse_snd_card_status(parms, &card, &status) < 0)
6977 return;
6978
6979 pthread_mutex_lock(&adev->lock);
6980 bool valid_cb = (card == adev->snd_card);
6981 pthread_mutex_unlock(&adev->lock);
6982
6983 if (!valid_cb)
6984 return;
6985
6986 lock_input_stream(in);
6987 if (in->card_status != status)
6988 in->card_status = status;
6989 pthread_mutex_unlock(&in->lock);
6990
6991 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6992 use_case_table[in->usecase],
6993 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6994
6995 // a better solution would be to report error back to AF and let
6996 // it put the stream to standby
6997 if (status == CARD_STATUS_OFFLINE)
6998 in_standby(&in->stream.common);
6999
7000 return;
7001}
7002
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007003int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007004 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007005 audio_source_t source)
7006{
7007 struct audio_device *adev = in->dev;
7008 int ret = 0;
7009
7010 lock_input_stream(in);
7011 pthread_mutex_lock(&adev->lock);
7012
7013 /* no audio source uses val == 0 */
7014 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7015 in->source = source;
7016 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7017 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7018 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7019 (in->config.rate == 8000 || in->config.rate == 16000 ||
7020 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7021 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7022 ret = voice_extn_compress_voip_open_input_stream(in);
7023 if (ret != 0) {
7024 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7025 __func__, ret);
7026 }
7027 }
7028 }
7029
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007030 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7031 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007032 // Workaround: If routing to an non existing usb device, fail gracefully
7033 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007034 struct str_parms *usb_addr =
7035 str_parms_create_str(get_usb_device_address(devices));
7036 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007037 !audio_extn_usb_connected(NULL)) {
7038 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007039 ret = -ENOSYS;
7040 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007041 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007042 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007043 if (!in->standby && !in->is_st_session) {
7044 ALOGV("update input routing change");
7045 // inform adm before actual routing to prevent glitches.
7046 if (adev->adm_on_routing_change) {
7047 adev->adm_on_routing_change(adev->adm_data,
7048 in->capture_handle);
7049 ret = select_devices(adev, in->usecase);
7050 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7051 adev->adm_routing_changed = true;
7052 }
7053 }
7054 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007055 if (usb_addr)
7056 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007057 }
7058 pthread_mutex_unlock(&adev->lock);
7059 pthread_mutex_unlock(&in->lock);
7060
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007061 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007062 return ret;
7063}
7064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007065static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7066{
7067 struct stream_in *in = (struct stream_in *)stream;
7068 struct audio_device *adev = in->dev;
7069 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007070 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307071 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007072
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307073 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007074 parms = str_parms_create_str(kvpairs);
7075
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307076 if (!parms)
7077 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007078 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007079 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007080
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307081 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7082 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307083 strlcpy(in->profile, value, sizeof(in->profile));
7084 ALOGV("updating stream profile with value '%s'", in->profile);
7085 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7086 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007087 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307088 in->sample_rate, in->bit_width,
7089 in->profile, &in->app_type_cfg);
7090 }
7091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007093 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007094
7095 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307096error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307097 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007098}
7099
7100static char* in_get_parameters(const struct audio_stream *stream,
7101 const char *keys)
7102{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007103 struct stream_in *in = (struct stream_in *)stream;
7104 struct str_parms *query = str_parms_create_str(keys);
7105 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007106 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007107
7108 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007109 if (reply) {
7110 str_parms_destroy(reply);
7111 }
7112 if (query) {
7113 str_parms_destroy(query);
7114 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007115 ALOGE("in_get_parameters: failed to create query or reply");
7116 return NULL;
7117 }
7118
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007119 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007120
7121 voice_extn_in_get_parameters(in, query, reply);
7122
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007123 stream_get_parameter_channels(query, reply,
7124 &in->supported_channel_masks[0]);
7125 stream_get_parameter_formats(query, reply,
7126 &in->supported_formats[0]);
7127 stream_get_parameter_rates(query, reply,
7128 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007129 str = str_parms_to_str(reply);
7130 str_parms_destroy(query);
7131 str_parms_destroy(reply);
7132
7133 ALOGV("%s: exit: returns - %s", __func__, str);
7134 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007135}
7136
Aalique Grahame22e49102018-12-18 14:23:57 -08007137static int in_set_gain(struct audio_stream_in *stream,
7138 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139{
Aalique Grahame22e49102018-12-18 14:23:57 -08007140 struct stream_in *in = (struct stream_in *)stream;
7141 char mixer_ctl_name[128];
7142 struct mixer_ctl *ctl;
7143 int ctl_value;
7144
7145 ALOGV("%s: gain %f", __func__, gain);
7146
7147 if (stream == NULL)
7148 return -EINVAL;
7149
7150 /* in_set_gain() only used to silence MMAP capture for now */
7151 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7152 return -ENOSYS;
7153
7154 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7155
7156 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7157 if (!ctl) {
7158 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7159 __func__, mixer_ctl_name);
7160 return -ENOSYS;
7161 }
7162
7163 if (gain < RECORD_GAIN_MIN)
7164 gain = RECORD_GAIN_MIN;
7165 else if (gain > RECORD_GAIN_MAX)
7166 gain = RECORD_GAIN_MAX;
7167 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7168
7169 mixer_ctl_set_value(ctl, 0, ctl_value);
7170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007171 return 0;
7172}
7173
7174static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7175 size_t bytes)
7176{
7177 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307178
7179 if (in == NULL) {
7180 ALOGE("%s: stream_in ptr is NULL", __func__);
7181 return -EINVAL;
7182 }
7183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007184 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307185 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307186 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007187
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007188 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307189
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007190 if (in->is_st_session) {
7191 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7192 /* Read from sound trigger HAL */
7193 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007194 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007195 if (adev->num_va_sessions < UINT_MAX)
7196 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007197 in->standby = 0;
7198 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007199 pthread_mutex_unlock(&in->lock);
7200 return bytes;
7201 }
7202
Haynes Mathew George16081042017-05-31 17:16:49 -07007203 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7204 ret = -ENOSYS;
7205 goto exit;
7206 }
7207
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007208 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7209 !in->standby && adev->adm_routing_changed) {
7210 ret = -ENOSYS;
7211 goto exit;
7212 }
7213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007214 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007215 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7216
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007217 pthread_mutex_lock(&adev->lock);
7218 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7219 ret = voice_extn_compress_voip_start_input_stream(in);
7220 else
7221 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007222 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7223 if (adev->num_va_sessions < UINT_MAX)
7224 adev->num_va_sessions++;
7225 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007226 pthread_mutex_unlock(&adev->lock);
7227 if (ret != 0) {
7228 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007229 }
7230 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007231
7232 // log startup time in ms.
7233 simple_stats_log(
7234 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307237 /* Avoid read if capture_stopped is set */
7238 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7239 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7240 ret = -EINVAL;
7241 goto exit;
7242 }
7243
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007244 // what's the duration requested by the client?
7245 long ns = 0;
7246
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307247 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007248 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7249 in->config.rate;
7250
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007251 ret = request_in_focus(in, ns);
7252 if (ret != 0)
7253 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007254 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007255
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307256 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307257 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7258 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307259 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007260 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307261 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007262 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007263 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007264 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007265 } else if (audio_extn_ffv_get_stream() == in) {
7266 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307267 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007268 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307269 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7270 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7271 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7272 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307273 ret = -EINVAL;
7274 goto exit;
7275 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307276 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307277 ret = -errno;
7278 }
7279 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307280 /* bytes read is always set to bytes for non compress usecases */
7281 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007282 }
7283
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007284 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007286 /*
Quinn Malef6050362019-01-30 15:55:40 -08007287 * Instead of writing zeroes here, we could trust the hardware to always
7288 * provide zeroes when muted. This is also muted with voice recognition
7289 * usecases so that other clients do not have access to voice recognition
7290 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007291 */
Quinn Malef6050362019-01-30 15:55:40 -08007292 if ((ret == 0 && voice_get_mic_mute(adev) &&
7293 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007294 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7295 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007296 (adev->num_va_sessions &&
7297 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7298 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7299 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007300 memset(buffer, 0, bytes);
7301
7302exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307303 frame_size = audio_stream_in_frame_size(stream);
7304 if (frame_size > 0)
7305 in->frames_read += bytes_read/frame_size;
7306
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007307 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307308 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007309 pthread_mutex_unlock(&in->lock);
7310
7311 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307312 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307313 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307314 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307315 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307316 in->standby = true;
7317 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307318 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307319 bytes_read = bytes;
7320 memset(buffer, 0, bytes);
7321 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007322 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007323 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7324 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007325 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307326 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307327 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007328 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307329 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007330}
7331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007332static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333{
7334 return 0;
7335}
7336
Aalique Grahame22e49102018-12-18 14:23:57 -08007337static int in_get_capture_position(const struct audio_stream_in *stream,
7338 int64_t *frames, int64_t *time)
7339{
7340 if (stream == NULL || frames == NULL || time == NULL) {
7341 return -EINVAL;
7342 }
7343 struct stream_in *in = (struct stream_in *)stream;
7344 int ret = -ENOSYS;
7345
7346 lock_input_stream(in);
7347 // note: ST sessions do not close the alsa pcm driver synchronously
7348 // on standby. Therefore, we may return an error even though the
7349 // pcm stream is still opened.
7350 if (in->standby) {
7351 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7352 "%s stream in standby but pcm not NULL for non ST session", __func__);
7353 goto exit;
7354 }
7355 if (in->pcm) {
7356 struct timespec timestamp;
7357 unsigned int avail;
7358 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7359 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007360 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007361 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307362 //Adjustment accounts for A2dp decoder latency for recording usecase
7363 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7364 if (is_a2dp_in_device_type(&in->device_list))
7365 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007366 ret = 0;
7367 }
7368 }
7369exit:
7370 pthread_mutex_unlock(&in->lock);
7371 return ret;
7372}
7373
Carter Hsu2e429db2019-05-14 18:50:52 +08007374static int in_update_effect_list(bool add, effect_handle_t effect,
7375 struct listnode *head)
7376{
7377 struct listnode *node;
7378 struct in_effect_list *elist = NULL;
7379 struct in_effect_list *target = NULL;
7380 int ret = 0;
7381
7382 if (!head)
7383 return ret;
7384
7385 list_for_each(node, head) {
7386 elist = node_to_item(node, struct in_effect_list, list);
7387 if (elist->handle == effect) {
7388 target = elist;
7389 break;
7390 }
7391 }
7392
7393 if (add) {
7394 if (target) {
7395 ALOGD("effect %p already exist", effect);
7396 return ret;
7397 }
7398
7399 target = (struct in_effect_list *)
7400 calloc(1, sizeof(struct in_effect_list));
7401
7402 if (!target) {
7403 ALOGE("%s:fail to allocate memory", __func__);
7404 return -ENOMEM;
7405 }
7406
7407 target->handle = effect;
7408 list_add_tail(head, &target->list);
7409 } else {
7410 if (target) {
7411 list_remove(&target->list);
7412 free(target);
7413 }
7414 }
7415
7416 return ret;
7417}
7418
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007419static int add_remove_audio_effect(const struct audio_stream *stream,
7420 effect_handle_t effect,
7421 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007422{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007423 struct stream_in *in = (struct stream_in *)stream;
7424 int status = 0;
7425 effect_descriptor_t desc;
7426
7427 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007428 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7429
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007430 if (status != 0)
7431 return status;
7432
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007433 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007434 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007435 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007436 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7437 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007438 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007439
7440 in_update_effect_list(enable, effect, &in->aec_list);
7441 enable = !list_empty(&in->aec_list);
7442 if (enable == in->enable_aec)
7443 goto exit;
7444
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007445 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007446 ALOGD("AEC enable %d", enable);
7447
Aalique Grahame22e49102018-12-18 14:23:57 -08007448 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7449 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7450 in->dev->enable_voicerx = enable;
7451 struct audio_usecase *usecase;
7452 struct listnode *node;
7453 list_for_each(node, &in->dev->usecase_list) {
7454 usecase = node_to_item(node, struct audio_usecase, list);
7455 if (usecase->type == PCM_PLAYBACK)
7456 select_devices(in->dev, usecase->id);
7457 }
7458 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007459 if (!in->standby) {
7460 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7461 select_devices(in->dev, in->usecase);
7462 }
7463
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007464 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007465 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7466
7467 in_update_effect_list(enable, effect, &in->ns_list);
7468 enable = !list_empty(&in->ns_list);
7469 if (enable == in->enable_ns)
7470 goto exit;
7471
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007472 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007473 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007474 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007475 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7476 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007477 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7478 select_devices(in->dev, in->usecase);
7479 } else
7480 select_devices(in->dev, in->usecase);
7481 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007482 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007483exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007484 pthread_mutex_unlock(&in->dev->lock);
7485 pthread_mutex_unlock(&in->lock);
7486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007487 return 0;
7488}
7489
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007490static int in_add_audio_effect(const struct audio_stream *stream,
7491 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007492{
Eric Laurent994a6932013-07-17 11:51:42 -07007493 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007494 return add_remove_audio_effect(stream, effect, true);
7495}
7496
7497static int in_remove_audio_effect(const struct audio_stream *stream,
7498 effect_handle_t effect)
7499{
Eric Laurent994a6932013-07-17 11:51:42 -07007500 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007501 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007502}
7503
Haynes Mathew George16081042017-05-31 17:16:49 -07007504static int in_stop(const struct audio_stream_in* stream)
7505{
7506 struct stream_in *in = (struct stream_in *)stream;
7507 struct audio_device *adev = in->dev;
7508
7509 int ret = -ENOSYS;
7510 ALOGV("%s", __func__);
7511 pthread_mutex_lock(&adev->lock);
7512 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7513 in->capture_started && in->pcm != NULL) {
7514 pcm_stop(in->pcm);
7515 ret = stop_input_stream(in);
7516 in->capture_started = false;
7517 }
7518 pthread_mutex_unlock(&adev->lock);
7519 return ret;
7520}
7521
7522static int in_start(const struct audio_stream_in* stream)
7523{
7524 struct stream_in *in = (struct stream_in *)stream;
7525 struct audio_device *adev = in->dev;
7526 int ret = -ENOSYS;
7527
7528 ALOGV("%s in %p", __func__, in);
7529 pthread_mutex_lock(&adev->lock);
7530 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7531 !in->capture_started && in->pcm != NULL) {
7532 if (!in->capture_started) {
7533 ret = start_input_stream(in);
7534 if (ret == 0) {
7535 in->capture_started = true;
7536 }
7537 }
7538 }
7539 pthread_mutex_unlock(&adev->lock);
7540 return ret;
7541}
7542
Phil Burke0a86d12019-02-16 22:28:11 -08007543// Read offset for the positional timestamp from a persistent vendor property.
7544// This is to workaround apparent inaccuracies in the timing information that
7545// is used by the AAudio timing model. The inaccuracies can cause glitches.
7546static int64_t in_get_mmap_time_offset() {
7547 const int32_t kDefaultOffsetMicros = 0;
7548 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007549 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007550 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7551 return mmap_time_offset_micros * (int64_t)1000;
7552}
7553
Haynes Mathew George16081042017-05-31 17:16:49 -07007554static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7555 int32_t min_size_frames,
7556 struct audio_mmap_buffer_info *info)
7557{
7558 struct stream_in *in = (struct stream_in *)stream;
7559 struct audio_device *adev = in->dev;
7560 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007561 unsigned int offset1 = 0;
7562 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007563 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007564 uint32_t mmap_size = 0;
7565 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007566
7567 pthread_mutex_lock(&adev->lock);
7568 ALOGV("%s in %p", __func__, in);
7569
Sharad Sanglec6f32552018-05-04 16:15:38 +05307570 if (CARD_STATUS_OFFLINE == in->card_status||
7571 CARD_STATUS_OFFLINE == adev->card_status) {
7572 ALOGW("in->card_status or adev->card_status offline, try again");
7573 ret = -EIO;
7574 goto exit;
7575 }
7576
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307577 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007578 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7579 ret = -EINVAL;
7580 goto exit;
7581 }
7582 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7583 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7584 ALOGV("%s in %p", __func__, in);
7585 ret = -ENOSYS;
7586 goto exit;
7587 }
7588 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7589 if (in->pcm_device_id < 0) {
7590 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7591 __func__, in->pcm_device_id, in->usecase);
7592 ret = -EINVAL;
7593 goto exit;
7594 }
7595
7596 adjust_mmap_period_count(&in->config, min_size_frames);
7597
7598 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7599 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7600 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7601 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307602 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307603 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7604 in->card_status = CARD_STATUS_OFFLINE;
7605 adev->card_status = CARD_STATUS_OFFLINE;
7606 ret = -EIO;
7607 goto exit;
7608 }
7609
Haynes Mathew George16081042017-05-31 17:16:49 -07007610 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7611 step = "open";
7612 ret = -ENODEV;
7613 goto exit;
7614 }
7615
7616 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7617 if (ret < 0) {
7618 step = "begin";
7619 goto exit;
7620 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007621
juyuchen626833d2019-06-04 16:48:02 +08007622 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007623 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7624 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7625 info->burst_size_frames = in->config.period_size;
7626 ret = platform_get_mmap_data_fd(adev->platform,
7627 in->pcm_device_id, 1 /*capture*/,
7628 &info->shared_memory_fd,
7629 &mmap_size);
7630 if (ret < 0) {
7631 // Fall back to non exclusive mode
7632 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7633 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007634 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7635 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7636
Arun Mirpuri5d170872019-03-26 13:21:31 -07007637 if (mmap_size < buffer_size) {
7638 step = "mmap";
7639 goto exit;
7640 }
juyuchen626833d2019-06-04 16:48:02 +08007641 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007642 }
7643
7644 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007645
7646 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7647 if (ret < 0) {
7648 step = "commit";
7649 goto exit;
7650 }
7651
Phil Burke0a86d12019-02-16 22:28:11 -08007652 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7653
Haynes Mathew George16081042017-05-31 17:16:49 -07007654 in->standby = false;
7655 ret = 0;
7656
7657 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7658 __func__, info->shared_memory_address, info->buffer_size_frames);
7659
7660exit:
7661 if (ret != 0) {
7662 if (in->pcm == NULL) {
7663 ALOGE("%s: %s - %d", __func__, step, ret);
7664 } else {
7665 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7666 pcm_close(in->pcm);
7667 in->pcm = NULL;
7668 }
7669 }
7670 pthread_mutex_unlock(&adev->lock);
7671 return ret;
7672}
7673
7674static int in_get_mmap_position(const struct audio_stream_in *stream,
7675 struct audio_mmap_position *position)
7676{
7677 struct stream_in *in = (struct stream_in *)stream;
7678 ALOGVV("%s", __func__);
7679 if (position == NULL) {
7680 return -EINVAL;
7681 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307682 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007683 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307684 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007685 return -ENOSYS;
7686 }
7687 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307688 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007689 return -ENOSYS;
7690 }
7691 struct timespec ts = { 0, 0 };
7692 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7693 if (ret < 0) {
7694 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307695 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007696 return ret;
7697 }
Phil Burke0a86d12019-02-16 22:28:11 -08007698 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7699 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307700 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007701 return 0;
7702}
7703
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307704static int in_get_active_microphones(const struct audio_stream_in *stream,
7705 struct audio_microphone_characteristic_t *mic_array,
7706 size_t *mic_count) {
7707 struct stream_in *in = (struct stream_in *)stream;
7708 struct audio_device *adev = in->dev;
7709 ALOGVV("%s", __func__);
7710
7711 lock_input_stream(in);
7712 pthread_mutex_lock(&adev->lock);
7713 int ret = platform_get_active_microphones(adev->platform,
7714 audio_channel_count_from_in_mask(in->channel_mask),
7715 in->usecase, mic_array, mic_count);
7716 pthread_mutex_unlock(&adev->lock);
7717 pthread_mutex_unlock(&in->lock);
7718
7719 return ret;
7720}
7721
7722static int adev_get_microphones(const struct audio_hw_device *dev,
7723 struct audio_microphone_characteristic_t *mic_array,
7724 size_t *mic_count) {
7725 struct audio_device *adev = (struct audio_device *)dev;
7726 ALOGVV("%s", __func__);
7727
7728 pthread_mutex_lock(&adev->lock);
7729 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7730 pthread_mutex_unlock(&adev->lock);
7731
7732 return ret;
7733}
juyuchendb308c22019-01-21 11:57:17 -07007734
7735static void in_update_sink_metadata(struct audio_stream_in *stream,
7736 const struct sink_metadata *sink_metadata) {
7737
7738 if (stream == NULL
7739 || sink_metadata == NULL
7740 || sink_metadata->tracks == NULL) {
7741 return;
7742 }
7743
7744 int error = 0;
7745 struct stream_in *in = (struct stream_in *)stream;
7746 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007747 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007748 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007749
7750 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007751
7752 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007753 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007754
7755 lock_input_stream(in);
7756 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007757 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007758
Zhou Song62ea0282020-03-22 19:53:01 +08007759 is_ha_usecase = adev->ha_proxy_enable ?
7760 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7761 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7762 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007763 && adev->voice_tx_output != NULL) {
7764 /* Use the rx device from afe-proxy record to route voice call because
7765 there is no routing if tx device is on primary hal and rx device
7766 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007767 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007768
7769 if (!voice_is_call_state_active(adev)) {
7770 if (adev->mode == AUDIO_MODE_IN_CALL) {
7771 adev->current_call_output = adev->voice_tx_output;
7772 error = voice_start_call(adev);
7773 if (error != 0)
7774 ALOGE("%s: start voice call failed %d", __func__, error);
7775 }
7776 } else {
7777 adev->current_call_output = adev->voice_tx_output;
7778 voice_update_devices_for_all_voice_usecases(adev);
7779 }
7780 }
7781
7782 pthread_mutex_unlock(&adev->lock);
7783 pthread_mutex_unlock(&in->lock);
7784}
7785
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307786int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007787 audio_io_handle_t handle,
7788 audio_devices_t devices,
7789 audio_output_flags_t flags,
7790 struct audio_config *config,
7791 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007792 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007793{
7794 struct audio_device *adev = (struct audio_device *)dev;
7795 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307796 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007797 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007798 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307799 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007800 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7801 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7802 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7803 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007804 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007805 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7806 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007807 bool force_haptic_path =
7808 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007809 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007810#ifdef AUDIO_GKI_ENABLED
7811 __s32 *generic_dec;
7812#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007813 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007814
kunleizdff872d2018-08-20 14:40:33 +08007815 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007816 is_usb_dev = false;
7817 devices = AUDIO_DEVICE_OUT_SPEAKER;
7818 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7819 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007820 if (config->format == AUDIO_FORMAT_DEFAULT)
7821 config->format = AUDIO_FORMAT_PCM_16_BIT;
7822 if (config->sample_rate == 0)
7823 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7824 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7825 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007826 }
7827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007828 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007830 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7831
Mingming Yin3a941d42016-02-17 18:08:05 -08007832 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007833 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7834 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307835
7836
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007837 if (!out) {
7838 return -ENOMEM;
7839 }
7840
Haynes Mathew George204045b2015-02-25 20:32:03 -08007841 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007842 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007843 pthread_mutexattr_init(&latch_attr);
7844 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
7845 pthread_mutex_init(&out->latch_lock, &latch_attr);
7846 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08007847 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007848 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007850 if (devices == AUDIO_DEVICE_NONE)
7851 devices = AUDIO_DEVICE_OUT_SPEAKER;
7852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007853 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007854 list_init(&out->device_list);
7855 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007856 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007857 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007858 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307859 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307860 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7861 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7862 else
7863 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007864 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007865 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007866 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307867 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307868 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007869 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007870 out->hal_output_suspend_supported = 0;
7871 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307872 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307873 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307874 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007875 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007876
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307877 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307878 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007879 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7880
Aalique Grahame22e49102018-12-18 14:23:57 -08007881 if (direct_dev &&
7882 (audio_is_linear_pcm(out->format) ||
7883 config->format == AUDIO_FORMAT_DEFAULT) &&
7884 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7885 audio_format_t req_format = config->format;
7886 audio_channel_mask_t req_channel_mask = config->channel_mask;
7887 uint32_t req_sample_rate = config->sample_rate;
7888
7889 pthread_mutex_lock(&adev->lock);
7890 if (is_hdmi) {
7891 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7892 ret = read_hdmi_sink_caps(out);
7893 if (config->sample_rate == 0)
7894 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7895 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7896 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7897 if (config->format == AUDIO_FORMAT_DEFAULT)
7898 config->format = AUDIO_FORMAT_PCM_16_BIT;
7899 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007900 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7901 &config->format,
7902 &out->supported_formats[0],
7903 MAX_SUPPORTED_FORMATS,
7904 &config->channel_mask,
7905 &out->supported_channel_masks[0],
7906 MAX_SUPPORTED_CHANNEL_MASKS,
7907 &config->sample_rate,
7908 &out->supported_sample_rates[0],
7909 MAX_SUPPORTED_SAMPLE_RATES);
7910 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007911 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007912
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007913 pthread_mutex_unlock(&adev->lock);
7914 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007915 if (ret == -ENOSYS) {
7916 /* ignore and go with default */
7917 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007918 }
7919 // For MMAP NO IRQ, allow conversions in ADSP
7920 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7921 goto error_open;
7922 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007923 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007924 goto error_open;
7925 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007926
7927 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7928 config->sample_rate = req_sample_rate;
7929 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7930 config->channel_mask = req_channel_mask;
7931 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7932 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007933 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007934
7935 out->sample_rate = config->sample_rate;
7936 out->channel_mask = config->channel_mask;
7937 out->format = config->format;
7938 if (is_hdmi) {
7939 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7940 out->config = pcm_config_hdmi_multi;
7941 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7942 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7943 out->config = pcm_config_mmap_playback;
7944 out->stream.start = out_start;
7945 out->stream.stop = out_stop;
7946 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7947 out->stream.get_mmap_position = out_get_mmap_position;
7948 } else {
7949 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7950 out->config = pcm_config_hifi;
7951 }
7952
7953 out->config.rate = out->sample_rate;
7954 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7955 if (is_hdmi) {
7956 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7957 audio_bytes_per_sample(out->format));
7958 }
7959 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007960 }
7961
Derek Chenf6318be2017-06-12 17:16:24 -04007962 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007963 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007964 /* extract car audio stream index */
7965 out->car_audio_stream =
7966 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7967 if (out->car_audio_stream < 0) {
7968 ALOGE("%s: invalid car audio stream %x",
7969 __func__, out->car_audio_stream);
7970 ret = -EINVAL;
7971 goto error_open;
7972 }
Derek Chen5f67a942020-02-24 23:08:13 -08007973 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007974 }
7975
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007976 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007977 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007978 if (!voice_extn_is_compress_voip_supported()) {
7979 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7980 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007981 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307982 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007983 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7984 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007985 out->volume_l = INVALID_OUT_VOLUME;
7986 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007987
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007988 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007989 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007990 uint32_t channel_count =
7991 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307992 out->config.channels = channel_count;
7993
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007994 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7995 out->sample_rate, out->format,
7996 channel_count, false);
7997 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7998 if (frame_size != 0)
7999 out->config.period_size = buffer_size / frame_size;
8000 else
8001 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008002 }
8003 } else {
8004 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8005 voice_extn_compress_voip_is_active(out->dev)) &&
8006 (voice_extn_compress_voip_is_config_supported(config))) {
8007 ret = voice_extn_compress_voip_open_output_stream(out);
8008 if (ret != 0) {
8009 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8010 __func__, ret);
8011 goto error_open;
8012 }
Sujin Panicker19027262019-09-16 18:28:06 +05308013 } else {
8014 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8015 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008016 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008017 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008018 } else if (audio_is_linear_pcm(out->format) &&
8019 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8020 out->channel_mask = config->channel_mask;
8021 out->sample_rate = config->sample_rate;
8022 out->format = config->format;
8023 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8024 // does this change?
8025 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8026 out->config.rate = config->sample_rate;
8027 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8028 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8029 audio_bytes_per_sample(config->format));
8030 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008031 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308032 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308033 pthread_mutex_lock(&adev->lock);
8034 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8035 pthread_mutex_unlock(&adev->lock);
8036
8037 // reject offload during card offline to allow
8038 // fallback to s/w paths
8039 if (offline) {
8040 ret = -ENODEV;
8041 goto error_open;
8042 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008044 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8045 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8046 ALOGE("%s: Unsupported Offload information", __func__);
8047 ret = -EINVAL;
8048 goto error_open;
8049 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008050
Atul Khare3fa6e542017-08-09 00:56:17 +05308051 if (config->offload_info.format == 0)
8052 config->offload_info.format = config->format;
8053 if (config->offload_info.sample_rate == 0)
8054 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008055
Mingming Yin90310102013-11-13 16:57:00 -08008056 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308057 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008058 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008059 ret = -EINVAL;
8060 goto error_open;
8061 }
8062
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008063 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8064 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8065 (audio_extn_passthru_is_passthrough_stream(out)) &&
8066 !((config->sample_rate == 48000) ||
8067 (config->sample_rate == 96000) ||
8068 (config->sample_rate == 192000))) {
8069 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8070 __func__, config->sample_rate, config->offload_info.format);
8071 ret = -EINVAL;
8072 goto error_open;
8073 }
8074
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008075 out->compr_config.codec = (struct snd_codec *)
8076 calloc(1, sizeof(struct snd_codec));
8077
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008078 if (!out->compr_config.codec) {
8079 ret = -ENOMEM;
8080 goto error_open;
8081 }
8082
Dhananjay Kumarac341582017-02-23 23:42:25 +05308083 out->stream.pause = out_pause;
8084 out->stream.resume = out_resume;
8085 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308086 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308087 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008088 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308089 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008090 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308091 } else {
8092 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8093 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008094 }
vivek mehta446c3962015-09-14 10:57:35 -07008095
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308096 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8097 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008098#ifdef AUDIO_GKI_ENABLED
8099 /* out->compr_config.codec->reserved[1] is for flags */
8100 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8101#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308102 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008103#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308104 }
8105
vivek mehta446c3962015-09-14 10:57:35 -07008106 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008107 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008108 config->format == 0 && config->sample_rate == 0 &&
8109 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008110 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008111 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8112 } else {
8113 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8114 ret = -EEXIST;
8115 goto error_open;
8116 }
vivek mehta446c3962015-09-14 10:57:35 -07008117 }
8118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008119 if (config->offload_info.channel_mask)
8120 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008121 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008122 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008123 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008124 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308125 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008126 ret = -EINVAL;
8127 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008128 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008129
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008130 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008131 out->sample_rate = config->offload_info.sample_rate;
8132
Mingming Yin3ee55c62014-08-04 14:23:35 -07008133 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008134
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308135 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308136 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308137 audio_extn_dolby_send_ddp_endp_params(adev);
8138 audio_extn_dolby_set_dmid(adev);
8139 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008140
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008141 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008142 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008143 out->compr_config.codec->bit_rate =
8144 config->offload_info.bit_rate;
8145 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308146 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008147 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308148 /* Update bit width only for non passthrough usecases.
8149 * For passthrough usecases, the output will always be opened @16 bit
8150 */
8151 if (!audio_extn_passthru_is_passthrough_stream(out))
8152 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308153
8154 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008155#ifdef AUDIO_GKI_ENABLED
8156 /* out->compr_config.codec->reserved[1] is for flags */
8157 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8158 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8159#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308160 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8161 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008162#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308163
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008164 /*TODO: Do we need to change it for passthrough */
8165 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008166
Manish Dewangana6fc5442015-08-24 20:30:31 +05308167 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8168 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308169 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308170 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308171 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8172 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308173
8174 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8175 AUDIO_FORMAT_PCM) {
8176
8177 /*Based on platform support, configure appropriate alsa format for corresponding
8178 *hal input format.
8179 */
8180 out->compr_config.codec->format = hal_format_to_alsa(
8181 config->offload_info.format);
8182
Ashish Jain83a6cc22016-06-28 14:34:17 +05308183 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308184 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308185 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308186
Dhananjay Kumarac341582017-02-23 23:42:25 +05308187 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308188 *hal input format and alsa format might differ based on platform support.
8189 */
8190 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308191 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308192
8193 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8194
Deeraj Soman93155a62019-09-30 19:00:37 +05308195 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8196 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8197 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8198 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8199 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308200
Ashish Jainf1eaa582016-05-23 20:54:24 +05308201 /* Check if alsa session is configured with the same format as HAL input format,
8202 * if not then derive correct fragment size needed to accomodate the
8203 * conversion of HAL input format to alsa format.
8204 */
8205 audio_extn_utils_update_direct_pcm_fragment_size(out);
8206
8207 /*if hal input and output fragment size is different this indicates HAL input format is
8208 *not same as the alsa format
8209 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308210 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308211 /*Allocate a buffer to convert input data to the alsa configured format.
8212 *size of convert buffer is equal to the size required to hold one fragment size
8213 *worth of pcm data, this is because flinger does not write more than fragment_size
8214 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308215 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8216 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308217 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8218 ret = -ENOMEM;
8219 goto error_open;
8220 }
8221 }
8222 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8223 out->compr_config.fragment_size =
8224 audio_extn_passthru_get_buffer_size(&config->offload_info);
8225 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8226 } else {
8227 out->compr_config.fragment_size =
8228 platform_get_compress_offload_buffer_size(&config->offload_info);
8229 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8230 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008231
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308232 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8233 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8234 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008235 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8236#ifdef AUDIO_GKI_ENABLED
8237 generic_dec =
8238 &(out->compr_config.codec->options.generic.reserved[1]);
8239 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8240 AUDIO_OUTPUT_BIT_WIDTH;
8241#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308242 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008243#endif
8244 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008245
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308246 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8247 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8248 }
8249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008250 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8251 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008252
Manish Dewangan69426c82017-01-30 17:35:36 +05308253 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8254 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8255 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8256 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8257 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8258 } else {
8259 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8260 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008261
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308262 memset(&out->channel_map_param, 0,
8263 sizeof(struct audio_out_channel_map_param));
8264
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008265 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308266 out->send_next_track_params = false;
8267 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008268 out->offload_state = OFFLOAD_STATE_IDLE;
8269 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008270 out->writeAt.tv_sec = 0;
8271 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008272
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008273 audio_extn_dts_create_state_notifier_node(out->usecase);
8274
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008275 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8276 __func__, config->offload_info.version,
8277 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308278
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308279 /* Check if DSD audio format is supported in codec
8280 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308281 */
8282
8283 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308284 (!platform_check_codec_dsd_support(adev->platform) ||
8285 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308286 ret = -EINVAL;
8287 goto error_open;
8288 }
8289
Ashish Jain5106d362016-05-11 19:23:33 +05308290 /* Disable gapless if any of the following is true
8291 * passthrough playback
8292 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308293 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308294 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308295 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308296 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008297 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308298 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308299 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308300 check_and_set_gapless_mode(adev, false);
8301 } else
8302 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008303
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308304 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008305 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8306 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308307 if (config->format == AUDIO_FORMAT_DSD) {
8308 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008309#ifdef AUDIO_GKI_ENABLED
8310 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8311 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8312#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308313 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008314#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308315 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008316
8317 create_offload_callback_thread(out);
8318
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008319 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008320 switch (config->sample_rate) {
8321 case 0:
8322 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8323 break;
8324 case 8000:
8325 case 16000:
8326 case 48000:
8327 out->sample_rate = config->sample_rate;
8328 break;
8329 default:
8330 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8331 config->sample_rate);
8332 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8333 ret = -EINVAL;
8334 goto error_open;
8335 }
8336 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8337 switch (config->channel_mask) {
8338 case AUDIO_CHANNEL_NONE:
8339 case AUDIO_CHANNEL_OUT_STEREO:
8340 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8341 break;
8342 default:
8343 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8344 config->channel_mask);
8345 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8346 ret = -EINVAL;
8347 goto error_open;
8348 }
8349 switch (config->format) {
8350 case AUDIO_FORMAT_DEFAULT:
8351 case AUDIO_FORMAT_PCM_16_BIT:
8352 out->format = AUDIO_FORMAT_PCM_16_BIT;
8353 break;
8354 default:
8355 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8356 config->format);
8357 config->format = AUDIO_FORMAT_PCM_16_BIT;
8358 ret = -EINVAL;
8359 goto error_open;
8360 }
8361
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308362 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008363 if (ret != 0) {
8364 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008365 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008366 goto error_open;
8367 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008368 } else if (is_single_device_type_equal(&out->device_list,
8369 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008370 switch (config->sample_rate) {
8371 case 0:
8372 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8373 break;
8374 case 8000:
8375 case 16000:
8376 case 48000:
8377 out->sample_rate = config->sample_rate;
8378 break;
8379 default:
8380 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8381 config->sample_rate);
8382 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8383 ret = -EINVAL;
8384 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008385 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008386 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8387 switch (config->channel_mask) {
8388 case AUDIO_CHANNEL_NONE:
8389 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8390 break;
8391 case AUDIO_CHANNEL_OUT_STEREO:
8392 out->channel_mask = config->channel_mask;
8393 break;
8394 default:
8395 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8396 config->channel_mask);
8397 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8398 ret = -EINVAL;
8399 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008400 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008401 switch (config->format) {
8402 case AUDIO_FORMAT_DEFAULT:
8403 out->format = AUDIO_FORMAT_PCM_16_BIT;
8404 break;
8405 case AUDIO_FORMAT_PCM_16_BIT:
8406 out->format = config->format;
8407 break;
8408 default:
8409 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8410 config->format);
8411 config->format = AUDIO_FORMAT_PCM_16_BIT;
8412 ret = -EINVAL;
8413 break;
8414 }
8415 if (ret != 0)
8416 goto error_open;
8417
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008418 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8419 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008420 out->config.rate = out->sample_rate;
8421 out->config.channels =
8422 audio_channel_count_from_out_mask(out->channel_mask);
8423 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008424 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008425 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308426 unsigned int channels = 0;
8427 /*Update config params to default if not set by the caller*/
8428 if (config->sample_rate == 0)
8429 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8430 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8431 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8432 if (config->format == AUDIO_FORMAT_DEFAULT)
8433 config->format = AUDIO_FORMAT_PCM_16_BIT;
8434
8435 channels = audio_channel_count_from_out_mask(out->channel_mask);
8436
Varun Balaraje49253e2017-07-06 19:48:56 +05308437 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8438 out->usecase = get_interactive_usecase(adev);
8439 out->config = pcm_config_low_latency;
8440 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308441 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008442 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8443 out->flags);
8444 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008445 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8446 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8447 out->config = pcm_config_mmap_playback;
8448 out->stream.start = out_start;
8449 out->stream.stop = out_stop;
8450 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8451 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308452 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8453 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008454 out->hal_output_suspend_supported =
8455 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8456 out->dynamic_pm_qos_config_supported =
8457 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8458 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008459 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8460 } else {
8461 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8462 //the mixer path will be a string similar to "low-latency-playback resume"
8463 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8464 strlcat(out->pm_qos_mixer_path,
8465 " resume", MAX_MIXER_PATH_LEN);
8466 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8467 out->pm_qos_mixer_path);
8468 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308469 out->config = pcm_config_low_latency;
8470 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8471 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8472 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308473 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8474 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8475 if (out->config.period_size <= 0) {
8476 ALOGE("Invalid configuration period size is not valid");
8477 ret = -EINVAL;
8478 goto error_open;
8479 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008480 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8481 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8482 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008483 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8484 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8485 out->config = pcm_config_haptics_audio;
8486 if (force_haptic_path)
8487 adev->haptics_config = pcm_config_haptics_audio;
8488 else
8489 adev->haptics_config = pcm_config_haptics;
8490
Meng Wangd08ce322020-04-02 08:59:20 +08008491 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008492 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8493
8494 if (force_haptic_path) {
8495 out->config.channels = 1;
8496 adev->haptics_config.channels = 1;
8497 } else
8498 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 -08008499 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008500 ret = audio_extn_auto_hal_open_output_stream(out);
8501 if (ret) {
8502 ALOGE("%s: Failed to open output stream for bus device", __func__);
8503 ret = -EINVAL;
8504 goto error_open;
8505 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308506 } else {
8507 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008508 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8509 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308510 }
8511 out->hal_ip_format = format = out->format;
8512 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8513 out->hal_op_format = pcm_format_to_hal(out->config.format);
8514 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8515 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008516 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308517 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308518 if (out->hal_ip_format != out->hal_op_format) {
8519 uint32_t buffer_size = out->config.period_size *
8520 format_to_bitwidth_table[out->hal_op_format] *
8521 out->config.channels;
8522 out->convert_buffer = calloc(1, buffer_size);
8523 if (out->convert_buffer == NULL){
8524 ALOGE("Allocation failed for convert buffer for size %d",
8525 out->compr_config.fragment_size);
8526 ret = -ENOMEM;
8527 goto error_open;
8528 }
8529 ALOGD("Convert buffer allocated of size %d", buffer_size);
8530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008531 }
8532
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008533 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8534 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308535
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008536 /* TODO remove this hardcoding and check why width is zero*/
8537 if (out->bit_width == 0)
8538 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308539 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008540 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008541 &out->device_list, out->flags,
8542 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308543 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308544 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008545 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008546 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8547 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008548 if(adev->primary_output == NULL)
8549 adev->primary_output = out;
8550 else {
8551 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008552 ret = -EEXIST;
8553 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008554 }
8555 }
8556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008557 /* Check if this usecase is already existing */
8558 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008559 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8560 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008561 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008562 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008563 ret = -EEXIST;
8564 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008565 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008567 pthread_mutex_unlock(&adev->lock);
8568
8569 out->stream.common.get_sample_rate = out_get_sample_rate;
8570 out->stream.common.set_sample_rate = out_set_sample_rate;
8571 out->stream.common.get_buffer_size = out_get_buffer_size;
8572 out->stream.common.get_channels = out_get_channels;
8573 out->stream.common.get_format = out_get_format;
8574 out->stream.common.set_format = out_set_format;
8575 out->stream.common.standby = out_standby;
8576 out->stream.common.dump = out_dump;
8577 out->stream.common.set_parameters = out_set_parameters;
8578 out->stream.common.get_parameters = out_get_parameters;
8579 out->stream.common.add_audio_effect = out_add_audio_effect;
8580 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8581 out->stream.get_latency = out_get_latency;
8582 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008583#ifdef NO_AUDIO_OUT
8584 out->stream.write = out_write_for_no_output;
8585#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008586 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008587#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008588 out->stream.get_render_position = out_get_render_position;
8589 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008590 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008591
Haynes Mathew George16081042017-05-31 17:16:49 -07008592 if (out->realtime)
8593 out->af_period_multiplier = af_period_multiplier;
8594 else
8595 out->af_period_multiplier = 1;
8596
Andy Hunga1f48fa2019-07-01 18:14:53 -07008597 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008599 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008600 out->volume_l = PLAYBACK_GAIN_MAX;
8601 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008602 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008603 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008604
8605 config->format = out->stream.common.get_format(&out->stream.common);
8606 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8607 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308608 register_format(out->format, out->supported_formats);
8609 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8610 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008611
Aalique Grahame22e49102018-12-18 14:23:57 -08008612 out->error_log = error_log_create(
8613 ERROR_LOG_ENTRIES,
8614 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8615
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308616 /*
8617 By locking output stream before registering, we allow the callback
8618 to update stream's state only after stream's initial state is set to
8619 adev state.
8620 */
8621 lock_output_stream(out);
8622 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8623 pthread_mutex_lock(&adev->lock);
8624 out->card_status = adev->card_status;
8625 pthread_mutex_unlock(&adev->lock);
8626 pthread_mutex_unlock(&out->lock);
8627
Aalique Grahame22e49102018-12-18 14:23:57 -08008628 stream_app_type_cfg_init(&out->app_type_cfg);
8629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008630 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308631 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008632 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008633
8634 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8635 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8636 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008637 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308638 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008639 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008640 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308641 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8642 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008643 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8644 out->usecase, PCM_PLAYBACK);
8645 hdlr_stream_cfg.flags = out->flags;
8646 hdlr_stream_cfg.type = PCM_PLAYBACK;
8647 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8648 &hdlr_stream_cfg);
8649 if (ret) {
8650 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8651 out->adsp_hdlr_stream_handle = NULL;
8652 }
8653 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308654 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8655 is_direct_passthough, false);
8656 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8657 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008658 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008659 if (ret < 0) {
8660 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8661 out->ip_hdlr_handle = NULL;
8662 }
8663 }
Derek Chenf939fb72018-11-13 13:34:41 -08008664
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008665 ret = io_streams_map_insert(adev, &out->stream.common,
8666 out->handle, AUDIO_PATCH_HANDLE_NONE);
8667 if (ret != 0)
8668 goto error_open;
8669
Susan Wang6dd13092021-01-25 10:27:11 -05008670 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008671
8672 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008673 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008674 pthread_mutex_unlock(&adev->lock);
8675
Eric Laurent994a6932013-07-17 11:51:42 -07008676 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008677 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008678
8679error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308680 if (out->convert_buffer)
8681 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008682 free(out);
8683 *stream_out = NULL;
8684 ALOGD("%s: exit: ret %d", __func__, ret);
8685 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008686}
8687
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308688void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008689 struct audio_stream_out *stream)
8690{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008691 struct stream_out *out = (struct stream_out *)stream;
8692 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008693 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008694
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008695 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308696
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008697 io_streams_map_remove(adev, out->handle);
8698
Susan Wang6dd13092021-01-25 10:27:11 -05008699 // remove out_ctxt early to prevent the stream
8700 // being opened in a race condition
8701 pthread_mutex_lock(&adev->lock);
8702 list_remove(&out->out_ctxt.list);
8703 pthread_mutex_unlock(&adev->lock);
8704
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308705 // must deregister from sndmonitor first to prevent races
8706 // between the callback and close_stream
8707 audio_extn_snd_mon_unregister_listener(out);
8708
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008709 /* close adsp hdrl session before standby */
8710 if (out->adsp_hdlr_stream_handle) {
8711 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8712 if (ret)
8713 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8714 out->adsp_hdlr_stream_handle = NULL;
8715 }
8716
Manish Dewangan21a850a2017-08-14 12:03:55 +05308717 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008718 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8719 out->ip_hdlr_handle = NULL;
8720 }
8721
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008722 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308723 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008724 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308725 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308726 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008727 if(ret != 0)
8728 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8729 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008730 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008731 out_standby(&stream->common);
8732
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008733 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008734 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008735 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008736 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008737 if (out->compr_config.codec != NULL)
8738 free(out->compr_config.codec);
8739 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008740
Zhou Songbaddf9f2020-11-20 13:57:39 +08008741 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308742
Varun Balaraje49253e2017-07-06 19:48:56 +05308743 if (is_interactive_usecase(out->usecase))
8744 free_interactive_usecase(adev, out->usecase);
8745
Ashish Jain83a6cc22016-06-28 14:34:17 +05308746 if (out->convert_buffer != NULL) {
8747 free(out->convert_buffer);
8748 out->convert_buffer = NULL;
8749 }
8750
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008751 if (adev->voice_tx_output == out)
8752 adev->voice_tx_output = NULL;
8753
Aalique Grahame22e49102018-12-18 14:23:57 -08008754 error_log_destroy(out->error_log);
8755 out->error_log = NULL;
8756
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308757 if (adev->primary_output == out)
8758 adev->primary_output = NULL;
8759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008760 pthread_cond_destroy(&out->cond);
8761 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008762 pthread_mutex_destroy(&out->pre_lock);
8763 pthread_mutex_destroy(&out->latch_lock);
8764 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008765
8766 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008767 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008768 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008769 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008770}
8771
8772static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8773{
8774 struct audio_device *adev = (struct audio_device *)dev;
8775 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008776 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008777 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008778 int ret;
8779 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008780 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008781 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008782 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008783
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008784 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008785 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008786
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308787 if (!parms)
8788 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308789
Derek Chen6f293672019-04-01 01:40:24 -07008790 /* notify adev and input/output streams on the snd card status */
8791 adev_snd_mon_cb((void *)adev, parms);
8792
Weiyin Jiang24f55292020-12-22 14:35:46 +08008793 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8794 if (ret >= 0) {
8795 list_for_each(node, &adev->active_outputs_list) {
8796 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8797 streams_output_ctxt_t,
8798 list);
8799 out_snd_mon_cb((void *)out_ctxt->output, parms);
8800 }
Derek Chen6f293672019-04-01 01:40:24 -07008801
Weiyin Jiang24f55292020-12-22 14:35:46 +08008802 list_for_each(node, &adev->active_inputs_list) {
8803 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8804 streams_input_ctxt_t,
8805 list);
8806 in_snd_mon_cb((void *)in_ctxt->input, parms);
8807 }
Derek Chen6f293672019-04-01 01:40:24 -07008808 }
8809
Zhou Songd6d71752019-05-21 18:08:51 +08008810 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308811 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8812 if (ret >= 0) {
8813 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008814 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308815 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308816 /*
8817 * When ever BT_SCO=ON arrives, make sure to route
8818 * all use cases to SCO device, otherwise due to delay in
8819 * BT_SCO=ON and lack of synchronization with create audio patch
8820 * request for SCO device, some times use case not routed properly to
8821 * SCO device
8822 */
8823 struct audio_usecase *usecase;
8824 struct listnode *node;
8825 list_for_each(node, &adev->usecase_list) {
8826 usecase = node_to_item(node, struct audio_usecase, list);
Mingshu Pangef517202021-04-22 10:35:00 +08008827 if (usecase->stream.in && (usecase->type == PCM_CAPTURE ||
8828 usecase->type == VOICE_CALL) &&
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308829 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device))) {
8830 ALOGD("BT_SCO ON, switch all in use case to it");
8831 select_devices(adev, usecase->id);
8832 }
Mingshu Pangef517202021-04-22 10:35:00 +08008833 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
8834 usecase->type == VOICE_CALL) &&
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308835 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE))) {
8836 ALOGD("BT_SCO ON, switch all out use case to it");
8837 select_devices(adev, usecase->id);
8838 }
8839 }
8840 }
8841 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308842 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008843 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008844 }
8845 }
8846
8847 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008848 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008849 if (!strncmp(value, "false", 5) &&
8850 audio_extn_a2dp_source_is_suspended()) {
8851 struct audio_usecase *usecase;
8852 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008853 list_for_each(node, &adev->usecase_list) {
8854 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008855 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008856 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008857 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008858 reassign_device_list(&usecase->stream.in->device_list,
8859 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008860 select_devices(adev, usecase->id);
8861 }
Zhou Songd6d71752019-05-21 18:08:51 +08008862 }
8863 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308864 }
8865
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008866 status = voice_set_parameters(adev, parms);
8867 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008868 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008869
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008870 status = platform_set_parameters(adev->platform, parms);
8871 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008872 goto done;
8873
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008874 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8875 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008876 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008877 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8878 adev->bluetooth_nrec = true;
8879 else
8880 adev->bluetooth_nrec = false;
8881 }
8882
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008883 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8884 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8886 adev->screen_off = false;
8887 else
8888 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008889 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008890 }
8891
Eric Laurent4b084132018-10-19 17:33:43 -07008892 ret = str_parms_get_int(parms, "rotation", &val);
8893 if (ret >= 0) {
8894 bool reverse_speakers = false;
8895 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8896 switch (val) {
8897 // FIXME: note that the code below assumes that the speakers are in the correct placement
8898 // relative to the user when the device is rotated 90deg from its default rotation. This
8899 // assumption is device-specific, not platform-specific like this code.
8900 case 270:
8901 reverse_speakers = true;
8902 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8903 break;
8904 case 0:
8905 case 180:
8906 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8907 break;
8908 case 90:
8909 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8910 break;
8911 default:
8912 ALOGE("%s: unexpected rotation of %d", __func__, val);
8913 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008914 }
Eric Laurent4b084132018-10-19 17:33:43 -07008915 if (status == 0) {
8916 // check and set swap
8917 // - check if orientation changed and speaker active
8918 // - set rotation and cache the rotation value
8919 adev->camera_orientation =
8920 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8921 if (!audio_extn_is_maxx_audio_enabled())
8922 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8923 }
8924 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008925
Mingming Yin514a8bc2014-07-29 15:22:21 -07008926 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8927 if (ret >= 0) {
8928 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8929 adev->bt_wb_speech_enabled = true;
8930 else
8931 adev->bt_wb_speech_enabled = false;
8932 }
8933
Zhou Song12c29502019-03-16 10:37:18 +08008934 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8935 if (ret >= 0) {
8936 val = atoi(value);
8937 adev->swb_speech_mode = val;
8938 }
8939
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008940 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8941 if (ret >= 0) {
8942 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308943 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008944 if (audio_is_output_device(val) &&
8945 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008946 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008947 platform_get_controller_stream_from_params(parms, &controller, &stream);
8948 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8949 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008950 if (ret < 0) {
8951 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308952 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008953 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008954 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308955 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008956 /*
8957 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8958 * Per AudioPolicyManager, USB device is higher priority than WFD.
8959 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8960 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8961 * starting voice call on USB
8962 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008963 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308964 if (ret >= 0)
8965 audio_extn_usb_add_device(device, atoi(value));
8966
Zhou Song6f862822017-11-06 17:27:57 +08008967 if (!audio_extn_usb_is_tunnel_supported()) {
8968 ALOGV("detected USB connect .. disable proxy");
8969 adev->allow_afe_proxy_usage = false;
8970 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008971 }
8972 }
8973
8974 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8975 if (ret >= 0) {
8976 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308977 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008978 /*
8979 * The HDMI / Displayport disconnect handling has been moved to
8980 * audio extension to ensure that its parameters are not
8981 * invalidated prior to updating sysfs of the disconnect event
8982 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8983 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308984 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008985 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308986 if (ret >= 0)
8987 audio_extn_usb_remove_device(device, atoi(value));
8988
Zhou Song6f862822017-11-06 17:27:57 +08008989 if (!audio_extn_usb_is_tunnel_supported()) {
8990 ALOGV("detected USB disconnect .. enable proxy");
8991 adev->allow_afe_proxy_usage = true;
8992 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008993 }
8994 }
8995
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008996 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008997
8998 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008999 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309000 struct audio_usecase *usecase;
9001 struct listnode *node;
9002 list_for_each(node, &adev->usecase_list) {
9003 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08009004 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9005 continue;
9006
9007 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309008 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309009 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309010 ALOGD("Switching to speaker and muting the stream before select_devices");
9011 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309012 //force device switch to re configure encoder
9013 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309014 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009015 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309016 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309017 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009018 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009019 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009020 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009021 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9022 reassign_device_list(&usecase->stream.out->device_list,
9023 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9024 check_a2dp_restore_l(adev, usecase->stream.out, true);
9025 break;
9026 }
9027 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309028 }
9029 }
9030 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009031
9032 //handle vr audio setparam
9033 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9034 value, sizeof(value));
9035 if (ret >= 0) {
9036 ALOGI("Setting vr mode to be %s", value);
9037 if (!strncmp(value, "true", 4)) {
9038 adev->vr_audio_mode_enabled = true;
9039 ALOGI("Setting vr mode to true");
9040 } else if (!strncmp(value, "false", 5)) {
9041 adev->vr_audio_mode_enabled = false;
9042 ALOGI("Setting vr mode to false");
9043 } else {
9044 ALOGI("wrong vr mode set");
9045 }
9046 }
9047
Eric Laurent4b084132018-10-19 17:33:43 -07009048 //FIXME: to be replaced by proper video capture properties API
9049 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9050 if (ret >= 0) {
9051 int camera_facing = CAMERA_FACING_BACK;
9052 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9053 camera_facing = CAMERA_FACING_FRONT;
9054 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9055 camera_facing = CAMERA_FACING_BACK;
9056 else {
9057 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9058 goto done;
9059 }
9060 adev->camera_orientation =
9061 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9062 struct audio_usecase *usecase;
9063 struct listnode *node;
9064 list_for_each(node, &adev->usecase_list) {
9065 usecase = node_to_item(node, struct audio_usecase, list);
9066 struct stream_in *in = usecase->stream.in;
9067 if (usecase->type == PCM_CAPTURE && in != NULL &&
9068 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9069 select_devices(adev, in->usecase);
9070 }
9071 }
9072 }
9073
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309074 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009075done:
9076 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009077 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309078error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009079 ALOGV("%s: exit with code(%d)", __func__, status);
9080 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009081}
9082
9083static char* adev_get_parameters(const struct audio_hw_device *dev,
9084 const char *keys)
9085{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309086 ALOGD("%s:%s", __func__, keys);
9087
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009088 struct audio_device *adev = (struct audio_device *)dev;
9089 struct str_parms *reply = str_parms_create();
9090 struct str_parms *query = str_parms_create_str(keys);
9091 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309092 char value[256] = {0};
9093 int ret = 0;
9094
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009095 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009096 if (reply) {
9097 str_parms_destroy(reply);
9098 }
9099 if (query) {
9100 str_parms_destroy(query);
9101 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009102 ALOGE("adev_get_parameters: failed to create query or reply");
9103 return NULL;
9104 }
9105
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009106 //handle vr audio getparam
9107
9108 ret = str_parms_get_str(query,
9109 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9110 value, sizeof(value));
9111
9112 if (ret >= 0) {
9113 bool vr_audio_enabled = false;
9114 pthread_mutex_lock(&adev->lock);
9115 vr_audio_enabled = adev->vr_audio_mode_enabled;
9116 pthread_mutex_unlock(&adev->lock);
9117
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009118 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009119
9120 if (vr_audio_enabled) {
9121 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9122 "true");
9123 goto exit;
9124 } else {
9125 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9126 "false");
9127 goto exit;
9128 }
9129 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009130
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009131 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009132 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009133 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009134 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009135 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009136 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309137 pthread_mutex_unlock(&adev->lock);
9138
Naresh Tannirud7205b62014-06-20 02:54:48 +05309139exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009140 str = str_parms_to_str(reply);
9141 str_parms_destroy(query);
9142 str_parms_destroy(reply);
9143
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009144 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009145 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009146}
9147
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009148static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149{
9150 return 0;
9151}
9152
9153static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9154{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009155 int ret;
9156 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009157
9158 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9159
Haynes Mathew George5191a852013-09-11 14:19:36 -07009160 pthread_mutex_lock(&adev->lock);
9161 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009162 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009163 pthread_mutex_unlock(&adev->lock);
9164 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009165}
9166
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009167static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9168 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009169{
9170 return -ENOSYS;
9171}
9172
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009173static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9174 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009175{
9176 return -ENOSYS;
9177}
9178
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009179static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9180 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009181{
9182 return -ENOSYS;
9183}
9184
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009185static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9186 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009187{
9188 return -ENOSYS;
9189}
9190
9191static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9192{
9193 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009194 struct listnode *node;
9195 struct audio_usecase *usecase = NULL;
9196 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009198 pthread_mutex_lock(&adev->lock);
9199 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309200 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9201 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009202 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009203 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309204 adev->current_call_output = adev->primary_output;
9205 voice_start_call(adev);
9206 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009207 (mode == AUDIO_MODE_NORMAL ||
9208 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009209 list_for_each(node, &adev->usecase_list) {
9210 usecase = node_to_item(node, struct audio_usecase, list);
9211 if (usecase->type == VOICE_CALL)
9212 break;
9213 }
9214 if (usecase &&
9215 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9216 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9217 true);
9218 if (ret != 0) {
9219 /* default service interval was successfully updated,
9220 reopen USB backend with new service interval */
9221 check_usecases_codec_backend(adev,
9222 usecase,
9223 usecase->out_snd_device);
9224 }
9225 }
9226
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009227 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009228 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009229 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009230 // restore device for other active usecases after stop call
9231 list_for_each(node, &adev->usecase_list) {
9232 usecase = node_to_item(node, struct audio_usecase, list);
9233 select_devices(adev, usecase->id);
9234 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236 }
9237 pthread_mutex_unlock(&adev->lock);
9238 return 0;
9239}
9240
9241static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9242{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009243 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009244 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009245
9246 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009247 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009248 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009249
Derek Chend2530072014-11-24 12:39:14 -08009250 if (adev->ext_hw_plugin)
9251 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009252
9253 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009254 pthread_mutex_unlock(&adev->lock);
9255
9256 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009257}
9258
9259static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9260{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009261 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009262 return 0;
9263}
9264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009265static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009266 const struct audio_config *config)
9267{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009268 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009269
Aalique Grahame22e49102018-12-18 14:23:57 -08009270 /* Don't know if USB HIFI in this context so use true to be conservative */
9271 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9272 true /*is_usb_hifi */) != 0)
9273 return 0;
9274
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009275 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9276 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009277}
9278
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009279static bool adev_input_allow_hifi_record(struct audio_device *adev,
9280 audio_devices_t devices,
9281 audio_input_flags_t flags,
9282 audio_source_t source) {
9283 const bool allowed = true;
9284
9285 if (!audio_is_usb_in_device(devices))
9286 return !allowed;
9287
9288 switch (flags) {
9289 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009290 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009291 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9292 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009293 default:
9294 return !allowed;
9295 }
9296
9297 switch (source) {
9298 case AUDIO_SOURCE_DEFAULT:
9299 case AUDIO_SOURCE_MIC:
9300 case AUDIO_SOURCE_UNPROCESSED:
9301 break;
9302 default:
9303 return !allowed;
9304 }
9305
9306 switch (adev->mode) {
9307 case 0:
9308 break;
9309 default:
9310 return !allowed;
9311 }
9312
9313 return allowed;
9314}
9315
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009316static int adev_update_voice_comm_input_stream(struct stream_in *in,
9317 struct audio_config *config)
9318{
9319 bool valid_rate = (config->sample_rate == 8000 ||
9320 config->sample_rate == 16000 ||
9321 config->sample_rate == 32000 ||
9322 config->sample_rate == 48000);
9323 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9324
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009325 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009326 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009327 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9328 in->config = default_pcm_config_voip_copp;
9329 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9330 DEFAULT_VOIP_BUF_DURATION_MS,
9331 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009332 } else {
9333 ALOGW("%s No valid input in voip, use defaults"
9334 "sample rate %u, channel mask 0x%X",
9335 __func__, config->sample_rate, in->channel_mask);
9336 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009337 in->config.rate = config->sample_rate;
9338 in->sample_rate = config->sample_rate;
9339 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009340 //XXX needed for voice_extn_compress_voip_open_input_stream
9341 in->config.rate = config->sample_rate;
9342 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309343 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009344 voice_extn_compress_voip_is_active(in->dev)) &&
9345 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9346 valid_rate && valid_ch) {
9347 voice_extn_compress_voip_open_input_stream(in);
9348 // update rate entries to match config from AF
9349 in->config.rate = config->sample_rate;
9350 in->sample_rate = config->sample_rate;
9351 } else {
9352 ALOGW("%s compress voip not active, use defaults", __func__);
9353 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009354 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009355 return 0;
9356}
9357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009358static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009359 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009360 audio_devices_t devices,
9361 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009362 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309363 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009364 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009365 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009366{
9367 struct audio_device *adev = (struct audio_device *)dev;
9368 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009369 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009370 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009371 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309372 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009373 bool is_usb_dev = audio_is_usb_in_device(devices);
9374 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9375 devices,
9376 flags,
9377 source);
Andy Hung94320602018-10-29 18:31:12 -07009378 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9379 " sample_rate %u, channel_mask %#x, format %#x",
9380 __func__, flags, is_usb_dev, may_use_hifi_record,
9381 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309382
kunleizdff872d2018-08-20 14:40:33 +08009383 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009384 is_usb_dev = false;
9385 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9386 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9387 __func__, devices);
9388 }
9389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009390 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009391
9392 if (!(is_usb_dev && may_use_hifi_record)) {
9393 if (config->sample_rate == 0)
9394 config->sample_rate = 48000;
9395 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9396 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9397 if (config->format == AUDIO_FORMAT_DEFAULT)
9398 config->format = AUDIO_FORMAT_PCM_16_BIT;
9399
9400 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9401
Aalique Grahame22e49102018-12-18 14:23:57 -08009402 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9403 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009404 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009406
9407 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009408
9409 if (!in) {
9410 ALOGE("failed to allocate input stream");
9411 return -ENOMEM;
9412 }
9413
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309414 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309415 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9416 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009417 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009418 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009420 in->stream.common.get_sample_rate = in_get_sample_rate;
9421 in->stream.common.set_sample_rate = in_set_sample_rate;
9422 in->stream.common.get_buffer_size = in_get_buffer_size;
9423 in->stream.common.get_channels = in_get_channels;
9424 in->stream.common.get_format = in_get_format;
9425 in->stream.common.set_format = in_set_format;
9426 in->stream.common.standby = in_standby;
9427 in->stream.common.dump = in_dump;
9428 in->stream.common.set_parameters = in_set_parameters;
9429 in->stream.common.get_parameters = in_get_parameters;
9430 in->stream.common.add_audio_effect = in_add_audio_effect;
9431 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9432 in->stream.set_gain = in_set_gain;
9433 in->stream.read = in_read;
9434 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009435 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309436 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009437 in->stream.set_microphone_direction = in_set_microphone_direction;
9438 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009439 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009440
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009441 list_init(&in->device_list);
9442 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009443 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009444 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009445 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009446 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009447 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009448 in->bit_width = 16;
9449 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009450 in->direction = MIC_DIRECTION_UNSPECIFIED;
9451 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009452 list_init(&in->aec_list);
9453 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009454 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009455
Andy Hung94320602018-10-29 18:31:12 -07009456 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009457 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9458 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9459 /* Force channel config requested to mono if incall
9460 record is being requested for only uplink/downlink */
9461 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9462 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9463 ret = -EINVAL;
9464 goto err_open;
9465 }
9466 }
9467
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009468 if (is_usb_dev && may_use_hifi_record) {
9469 /* HiFi record selects an appropriate format, channel, rate combo
9470 depending on sink capabilities*/
9471 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9472 &config->format,
9473 &in->supported_formats[0],
9474 MAX_SUPPORTED_FORMATS,
9475 &config->channel_mask,
9476 &in->supported_channel_masks[0],
9477 MAX_SUPPORTED_CHANNEL_MASKS,
9478 &config->sample_rate,
9479 &in->supported_sample_rates[0],
9480 MAX_SUPPORTED_SAMPLE_RATES);
9481 if (ret != 0) {
9482 ret = -EINVAL;
9483 goto err_open;
9484 }
9485 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009486 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309487 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309488 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9489 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9490 in->config.format = PCM_FORMAT_S32_LE;
9491 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309492 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9493 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9494 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9495 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9496 bool ret_error = false;
9497 in->bit_width = 24;
9498 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9499 from HAL is 24_packed and 8_24
9500 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9501 24_packed return error indicating supported format is 24_packed
9502 *> In case of any other source requesting 24 bit or float return error
9503 indicating format supported is 16 bit only.
9504
9505 on error flinger will retry with supported format passed
9506 */
9507 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9508 (source != AUDIO_SOURCE_CAMCORDER)) {
9509 config->format = AUDIO_FORMAT_PCM_16_BIT;
9510 if (config->sample_rate > 48000)
9511 config->sample_rate = 48000;
9512 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009513 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9514 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309515 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9516 ret_error = true;
9517 }
9518
9519 if (ret_error) {
9520 ret = -EINVAL;
9521 goto err_open;
9522 }
9523 }
9524
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009525 in->channel_mask = config->channel_mask;
9526 in->format = config->format;
9527
9528 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309529
Huicheng Liu1404ba12020-09-11 01:03:25 -04009530 /* validate bus device address */
9531 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9532 /* extract car audio stream index */
9533 in->car_audio_stream =
9534 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9535 if (in->car_audio_stream < 0) {
9536 ALOGE("%s: invalid car audio stream %x",
9537 __func__, in->car_audio_stream);
9538 ret = -EINVAL;
9539 goto err_open;
9540 }
9541 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009542 ret = audio_extn_auto_hal_open_input_stream(in);
9543 if (ret) {
9544 ALOGE("%s: Failed to open input stream for bus device", __func__);
9545 ret = -EINVAL;
9546 goto err_open;
9547 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009548 }
9549
Susan Wange3959562021-03-11 11:50:26 -05009550 /* reassign use case for echo reference stream on automotive platforms */
9551 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9552 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9553 }
9554
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309555 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9556 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9557 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9558 else {
9559 ret = -EINVAL;
9560 goto err_open;
9561 }
9562 }
9563
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009564 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309565 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9566 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009567 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9568 is_low_latency = true;
9569#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309570 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9571 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9572 else
9573 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009574#endif
9575 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009576 if (!in->realtime) {
9577 in->config = pcm_config_audio_capture;
9578 frame_size = audio_stream_in_frame_size(&in->stream);
9579 buffer_size = get_input_buffer_size(config->sample_rate,
9580 config->format,
9581 channel_count,
9582 is_low_latency);
9583 in->config.period_size = buffer_size / frame_size;
9584 in->config.rate = config->sample_rate;
9585 in->af_period_multiplier = 1;
9586 } else {
9587 // period size is left untouched for rt mode playback
9588 in->config = pcm_config_audio_capture_rt;
9589 in->af_period_multiplier = af_period_multiplier;
9590 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009591 }
9592
9593 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9594 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9595 in->realtime = 0;
9596 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9597 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009598 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009599 in->stream.start = in_start;
9600 in->stream.stop = in_stop;
9601 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9602 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009603 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009604 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009605 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9606 in->config = pcm_config_audio_capture;
9607 frame_size = audio_stream_in_frame_size(&in->stream);
9608 buffer_size = get_input_buffer_size(config->sample_rate,
9609 config->format,
9610 channel_count,
9611 false /*is_low_latency*/);
9612 in->config.period_size = buffer_size / frame_size;
9613 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009614 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009615 switch (config->format) {
9616 case AUDIO_FORMAT_PCM_32_BIT:
9617 in->bit_width = 32;
9618 break;
9619 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9620 case AUDIO_FORMAT_PCM_8_24_BIT:
9621 in->bit_width = 24;
9622 break;
9623 default:
9624 in->bit_width = 16;
9625 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009626 } else if (is_single_device_type_equal(&in->device_list,
9627 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9628 is_single_device_type_equal(&in->device_list,
9629 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009630 if (config->sample_rate == 0)
9631 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9632 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9633 config->sample_rate != 8000) {
9634 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9635 ret = -EINVAL;
9636 goto err_open;
9637 }
9638 if (config->format == AUDIO_FORMAT_DEFAULT)
9639 config->format = AUDIO_FORMAT_PCM_16_BIT;
9640 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9641 config->format = AUDIO_FORMAT_PCM_16_BIT;
9642 ret = -EINVAL;
9643 goto err_open;
9644 }
9645
9646 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009647 if (adev->ha_proxy_enable &&
9648 is_single_device_type_equal(&in->device_list,
9649 AUDIO_DEVICE_IN_TELEPHONY_RX))
9650 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009651 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009652 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009653 in->af_period_multiplier = 1;
9654 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309655 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009656 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9657 (config->sample_rate == 8000 ||
9658 config->sample_rate == 16000 ||
9659 config->sample_rate == 32000 ||
9660 config->sample_rate == 48000) &&
9661 channel_count == 1) {
9662 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9663 in->config = pcm_config_audio_capture;
9664 frame_size = audio_stream_in_frame_size(&in->stream);
9665 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9666 config->sample_rate,
9667 config->format,
9668 channel_count, false /*is_low_latency*/);
9669 in->config.period_size = buffer_size / frame_size;
9670 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9671 in->config.rate = config->sample_rate;
9672 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009673 } else if (in->realtime) {
9674 in->config = pcm_config_audio_capture_rt;
9675 in->config.format = pcm_format_from_audio_format(config->format);
9676 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009677 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309678 int ret_val;
9679 pthread_mutex_lock(&adev->lock);
9680 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9681 in, config, &channel_mask_updated);
9682 pthread_mutex_unlock(&adev->lock);
9683
9684 if (!ret_val) {
9685 if (channel_mask_updated == true) {
9686 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9687 __func__, config->channel_mask);
9688 ret = -EINVAL;
9689 goto err_open;
9690 }
9691 ALOGD("%s: created multi-channel session succesfully",__func__);
9692 } else if (audio_extn_compr_cap_enabled() &&
9693 audio_extn_compr_cap_format_supported(config->format) &&
9694 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9695 audio_extn_compr_cap_init(in);
9696 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309697 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309698 if (ret)
9699 goto err_open;
9700 } else {
9701 in->config = pcm_config_audio_capture;
9702 in->config.rate = config->sample_rate;
9703 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309704 in->format = config->format;
9705 frame_size = audio_stream_in_frame_size(&in->stream);
9706 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009707 config->format,
9708 channel_count,
9709 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009710 /* prevent division-by-zero */
9711 if (frame_size == 0) {
9712 ALOGE("%s: Error frame_size==0", __func__);
9713 ret = -EINVAL;
9714 goto err_open;
9715 }
9716
Revathi Uddarajud2634032017-12-07 14:42:34 +05309717 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009718 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009719
Revathi Uddarajud2634032017-12-07 14:42:34 +05309720 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9721 /* optionally use VOIP usecase depending on config(s) */
9722 ret = adev_update_voice_comm_input_stream(in, config);
9723 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009724
Revathi Uddarajud2634032017-12-07 14:42:34 +05309725 if (ret) {
9726 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9727 goto err_open;
9728 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009729 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309730
9731 /* assign concurrent capture usecase if record has to caried out from
9732 * actual hardware input source */
9733 if (audio_extn_is_concurrent_capture_enabled() &&
9734 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309735 /* Acquire lock to avoid two concurrent use cases initialized to
9736 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009737
Samyak Jainc37062f2019-04-25 18:41:06 +05309738 if (in->usecase == USECASE_AUDIO_RECORD) {
9739 pthread_mutex_lock(&adev->lock);
9740 if (!(adev->pcm_record_uc_state)) {
9741 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9742 adev->pcm_record_uc_state = 1;
9743 pthread_mutex_unlock(&adev->lock);
9744 } else {
9745 pthread_mutex_unlock(&adev->lock);
9746 /* Assign compress record use case for second record */
9747 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9748 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9749 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9750 if (audio_extn_cin_applicable_stream(in)) {
9751 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309752 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309753 if (ret)
9754 goto err_open;
9755 }
9756 }
9757 }
kunleiz28c73e72019-03-27 17:24:04 +08009758 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009759 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309760 if (audio_extn_ssr_get_stream() != in)
9761 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009762
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009763 in->sample_rate = in->config.rate;
9764
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309765 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9766 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009767 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009768 in->sample_rate, in->bit_width,
9769 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309770 register_format(in->format, in->supported_formats);
9771 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9772 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309773
Aalique Grahame22e49102018-12-18 14:23:57 -08009774 in->error_log = error_log_create(
9775 ERROR_LOG_ENTRIES,
9776 1000000000 /* aggregate consecutive identical errors within one second */);
9777
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009778 /* This stream could be for sound trigger lab,
9779 get sound trigger pcm if present */
9780 audio_extn_sound_trigger_check_and_get_session(in);
9781
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309782 lock_input_stream(in);
9783 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9784 pthread_mutex_lock(&adev->lock);
9785 in->card_status = adev->card_status;
9786 pthread_mutex_unlock(&adev->lock);
9787 pthread_mutex_unlock(&in->lock);
9788
Aalique Grahame22e49102018-12-18 14:23:57 -08009789 stream_app_type_cfg_init(&in->app_type_cfg);
9790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009791 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009792
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009793 ret = io_streams_map_insert(adev, &in->stream.common,
9794 handle, AUDIO_PATCH_HANDLE_NONE);
9795 if (ret != 0)
9796 goto err_open;
9797
Susan Wang6dd13092021-01-25 10:27:11 -05009798 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009799
9800 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009801 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009802 pthread_mutex_unlock(&adev->lock);
9803
Eric Laurent994a6932013-07-17 11:51:42 -07009804 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009805 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009806
9807err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309808 if (in->usecase == USECASE_AUDIO_RECORD) {
9809 pthread_mutex_lock(&adev->lock);
9810 adev->pcm_record_uc_state = 0;
9811 pthread_mutex_unlock(&adev->lock);
9812 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009813 free(in);
9814 *stream_in = NULL;
9815 return ret;
9816}
9817
9818static void adev_close_input_stream(struct audio_hw_device *dev,
9819 struct audio_stream_in *stream)
9820{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009821 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009822 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009823 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309824
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309825 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009826
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009827 if (in == NULL) {
9828 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9829 return;
9830 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009831 io_streams_map_remove(adev, in->capture_handle);
9832
Susan Wang6dd13092021-01-25 10:27:11 -05009833 // remove out_ctxt early to prevent the stream
9834 // being opened in a race condition
9835 pthread_mutex_lock(&adev->lock);
9836 list_remove(&in->in_ctxt.list);
9837 pthread_mutex_unlock(&adev->lock);
9838
kunleiz70e57612018-12-28 17:50:23 +08009839 /* must deregister from sndmonitor first to prevent races
9840 * between the callback and close_stream
9841 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309842 audio_extn_snd_mon_unregister_listener(stream);
9843
kunleiz70e57612018-12-28 17:50:23 +08009844 /* Disable echo reference if there are no active input, hfp call
9845 * and sound trigger while closing input stream
9846 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009847 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009848 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009849 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9850 struct listnode out_devices;
9851 list_init(&out_devices);
9852 platform_set_echo_reference(adev, false, &out_devices);
9853 } else
kunleiz70e57612018-12-28 17:50:23 +08009854 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309855
Weiyin Jiang2995f662019-04-17 14:25:12 +08009856 error_log_destroy(in->error_log);
9857 in->error_log = NULL;
9858
Pallavid7c7a272018-01-16 11:22:55 +05309859
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009860 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309861 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009862 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309863 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009864 if (ret != 0)
9865 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9866 __func__, ret);
9867 } else
9868 in_standby(&stream->common);
9869
Weiyin Jiang280ea742020-09-08 20:28:22 +08009870 pthread_mutex_destroy(&in->lock);
9871 pthread_mutex_destroy(&in->pre_lock);
9872
Revathi Uddarajud2634032017-12-07 14:42:34 +05309873 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309874 if (in->usecase == USECASE_AUDIO_RECORD) {
9875 adev->pcm_record_uc_state = 0;
9876 }
9877
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009878 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9879 adev->enable_voicerx = false;
9880 }
9881
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009882 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009883 audio_extn_ssr_deinit();
9884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009885
Garmond Leunge2433c32017-09-28 21:51:22 -07009886 if (audio_extn_ffv_get_stream() == in) {
9887 audio_extn_ffv_stream_deinit();
9888 }
9889
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309890 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009891 audio_extn_compr_cap_format_supported(in->config.format))
9892 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309893
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309894 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309895 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009896
Mingming Yinfd7607b2016-01-22 12:48:44 -08009897 if (in->is_st_session) {
9898 ALOGV("%s: sound trigger pcm stop lab", __func__);
9899 audio_extn_sound_trigger_stop_lab(in);
9900 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009901 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309902 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009903 return;
9904}
9905
Aalique Grahame22e49102018-12-18 14:23:57 -08009906/* verifies input and output devices and their capabilities.
9907 *
9908 * This verification is required when enabling extended bit-depth or
9909 * sampling rates, as not all qcom products support it.
9910 *
9911 * Suitable for calling only on initialization such as adev_open().
9912 * It fills the audio_device use_case_table[] array.
9913 *
9914 * Has a side-effect that it needs to configure audio routing / devices
9915 * in order to power up the devices and read the device parameters.
9916 * It does not acquire any hw device lock. Should restore the devices
9917 * back to "normal state" upon completion.
9918 */
9919static int adev_verify_devices(struct audio_device *adev)
9920{
9921 /* enumeration is a bit difficult because one really wants to pull
9922 * the use_case, device id, etc from the hidden pcm_device_table[].
9923 * In this case there are the following use cases and device ids.
9924 *
9925 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9926 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9927 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9928 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9929 * [USECASE_AUDIO_RECORD] = {0, 0},
9930 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9931 * [USECASE_VOICE_CALL] = {2, 2},
9932 *
9933 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9934 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9935 */
9936
9937 /* should be the usecases enabled in adev_open_input_stream() */
9938 static const int test_in_usecases[] = {
9939 USECASE_AUDIO_RECORD,
9940 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9941 };
9942 /* should be the usecases enabled in adev_open_output_stream()*/
9943 static const int test_out_usecases[] = {
9944 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9945 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9946 };
9947 static const usecase_type_t usecase_type_by_dir[] = {
9948 PCM_PLAYBACK,
9949 PCM_CAPTURE,
9950 };
9951 static const unsigned flags_by_dir[] = {
9952 PCM_OUT,
9953 PCM_IN,
9954 };
9955
9956 size_t i;
9957 unsigned dir;
9958 const unsigned card_id = adev->snd_card;
9959
9960 for (dir = 0; dir < 2; ++dir) {
9961 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9962 const unsigned flags_dir = flags_by_dir[dir];
9963 const size_t testsize =
9964 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9965 const int *testcases =
9966 dir ? test_in_usecases : test_out_usecases;
9967 const audio_devices_t audio_device =
9968 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9969
9970 for (i = 0; i < testsize; ++i) {
9971 const audio_usecase_t audio_usecase = testcases[i];
9972 int device_id;
9973 struct pcm_params **pparams;
9974 struct stream_out out;
9975 struct stream_in in;
9976 struct audio_usecase uc_info;
9977 int retval;
9978
9979 pparams = &adev->use_case_table[audio_usecase];
9980 pcm_params_free(*pparams); /* can accept null input */
9981 *pparams = NULL;
9982
9983 /* find the device ID for the use case (signed, for error) */
9984 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9985 if (device_id < 0)
9986 continue;
9987
9988 /* prepare structures for device probing */
9989 memset(&uc_info, 0, sizeof(uc_info));
9990 uc_info.id = audio_usecase;
9991 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009992 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009993 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009994 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009995 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009996 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009997 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9998 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009999 }
10000 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010001 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010002 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010003 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010004 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010005 uc_info.in_snd_device = SND_DEVICE_NONE;
10006 uc_info.out_snd_device = SND_DEVICE_NONE;
10007 list_add_tail(&adev->usecase_list, &uc_info.list);
10008
10009 /* select device - similar to start_(in/out)put_stream() */
10010 retval = select_devices(adev, audio_usecase);
10011 if (retval >= 0) {
10012 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10013#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010014 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010015 if (*pparams) {
10016 ALOGV("%s: (%s) card %d device %d", __func__,
10017 dir ? "input" : "output", card_id, device_id);
10018 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10019 } else {
10020 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10021 }
10022#endif
10023 }
10024
10025 /* deselect device - similar to stop_(in/out)put_stream() */
10026 /* 1. Get and set stream specific mixer controls */
10027 retval = disable_audio_route(adev, &uc_info);
10028 /* 2. Disable the rx device */
10029 retval = disable_snd_device(adev,
10030 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10031 list_remove(&uc_info.list);
10032 }
10033 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010034 return 0;
10035}
10036
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037int update_patch(unsigned int num_sources,
10038 const struct audio_port_config *sources,
10039 unsigned int num_sinks,
10040 const struct audio_port_config *sinks,
10041 audio_patch_handle_t handle,
10042 struct audio_patch_info *p_info,
10043 patch_type_t patch_type, bool new_patch)
10044{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010045 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010046
10047 if (p_info == NULL) {
10048 ALOGE("%s: Invalid patch pointer", __func__);
10049 return -EINVAL;
10050 }
10051
10052 if (new_patch) {
10053 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10054 if (p_info->patch == NULL) {
10055 ALOGE("%s: Could not allocate patch", __func__);
10056 return -ENOMEM;
10057 }
10058 }
10059
10060 p_info->patch->id = handle;
10061 p_info->patch->num_sources = num_sources;
10062 p_info->patch->num_sinks = num_sinks;
10063
10064 for (int i = 0; i < num_sources; i++)
10065 p_info->patch->sources[i] = sources[i];
10066 for (int i = 0; i < num_sinks; i++)
10067 p_info->patch->sinks[i] = sinks[i];
10068
10069 p_info->patch_type = patch_type;
10070 return 0;
10071}
10072
10073audio_patch_handle_t generate_patch_handle()
10074{
10075 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10076 if (++patch_handle < 0)
10077 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10078 return patch_handle;
10079}
10080
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010081int adev_create_audio_patch(struct audio_hw_device *dev,
10082 unsigned int num_sources,
10083 const struct audio_port_config *sources,
10084 unsigned int num_sinks,
10085 const struct audio_port_config *sinks,
10086 audio_patch_handle_t *handle)
10087{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010088 int ret = 0;
10089 struct audio_device *adev = (struct audio_device *)dev;
10090 struct audio_patch_info *p_info = NULL;
10091 patch_type_t patch_type = PATCH_NONE;
10092 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10093 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10094 struct audio_stream_info *s_info = NULL;
10095 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010096 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10098 bool new_patch = false;
10099 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010100
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010101 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10102 num_sources, num_sinks, *handle);
10103
10104 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10105 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10106 ALOGE("%s: Invalid patch arguments", __func__);
10107 ret = -EINVAL;
10108 goto done;
10109 }
10110
10111 if (num_sources > 1) {
10112 ALOGE("%s: Multiple sources are not supported", __func__);
10113 ret = -EINVAL;
10114 goto done;
10115 }
10116
10117 if (sources == NULL || sinks == NULL) {
10118 ALOGE("%s: Invalid sources or sinks port config", __func__);
10119 ret = -EINVAL;
10120 goto done;
10121 }
10122
10123 ALOGV("%s: source role %d, source type %d", __func__,
10124 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010125 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010126
10127 // Populate source/sink information and fetch stream info
10128 switch (sources[0].type) {
10129 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10130 device_type = sources[0].ext.device.type;
10131 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010132 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010133 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10134 patch_type = PATCH_CAPTURE;
10135 io_handle = sinks[0].ext.mix.handle;
10136 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010137 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010138 __func__, device_type, io_handle);
10139 } else {
10140 // Device to device patch is not implemented.
10141 // This space will need changes if audio HAL
10142 // handles device to device patches in the future.
10143 patch_type = PATCH_DEVICE_LOOPBACK;
10144 }
10145 break;
10146 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10147 io_handle = sources[0].ext.mix.handle;
10148 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010149 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010150 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010151 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 }
10153 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010154 ALOGD("%s: Playback patch from mix handle %d to device %x",
10155 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010156 break;
10157 case AUDIO_PORT_TYPE_SESSION:
10158 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010159 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10160 ret = -EINVAL;
10161 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 }
10163
10164 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010165
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010166 // Generate patch info and update patch
10167 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010168 *handle = generate_patch_handle();
10169 p_info = (struct audio_patch_info *)
10170 calloc(1, sizeof(struct audio_patch_info));
10171 if (p_info == NULL) {
10172 ALOGE("%s: Failed to allocate memory", __func__);
10173 pthread_mutex_unlock(&adev->lock);
10174 ret = -ENOMEM;
10175 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010176 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010177 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010178 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010179 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010180 if (p_info == NULL) {
10181 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10182 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010183 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010184 ret = -EINVAL;
10185 goto done;
10186 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010188 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010189 *handle, p_info, patch_type, new_patch);
10190
10191 // Fetch stream info of associated mix for playback or capture patches
10192 if (p_info->patch_type == PATCH_PLAYBACK ||
10193 p_info->patch_type == PATCH_CAPTURE) {
10194 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10195 if (s_info == NULL) {
10196 ALOGE("%s: Failed to obtain stream info", __func__);
10197 if (new_patch)
10198 free(p_info);
10199 pthread_mutex_unlock(&adev->lock);
10200 ret = -EINVAL;
10201 goto done;
10202 }
10203 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10204 s_info->patch_handle = *handle;
10205 stream = s_info->stream;
10206 }
10207 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010208
10209 // Update routing for stream
10210 if (stream != NULL) {
10211 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010212 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010213 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010214 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010215 if (ret < 0) {
10216 pthread_mutex_lock(&adev->lock);
10217 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10218 if (new_patch)
10219 free(p_info);
10220 pthread_mutex_unlock(&adev->lock);
10221 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10222 goto done;
10223 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010224 }
10225
10226 // Add new patch to patch map
10227 if (!ret && new_patch) {
10228 pthread_mutex_lock(&adev->lock);
10229 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010230 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010231 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010232 }
10233
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010234done:
10235 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010236 num_sources,
10237 sources,
10238 num_sinks,
10239 sinks,
10240 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010241 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010242 num_sources,
10243 sources,
10244 num_sinks,
10245 sinks,
10246 handle);
10247 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010248}
10249
10250int adev_release_audio_patch(struct audio_hw_device *dev,
10251 audio_patch_handle_t handle)
10252{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010253 struct audio_device *adev = (struct audio_device *) dev;
10254 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010255 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010256 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010257
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010258 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10259 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10260 ret = -EINVAL;
10261 goto done;
10262 }
10263
10264 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010265 pthread_mutex_lock(&adev->lock);
10266 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010267 if (p_info == NULL) {
10268 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010269 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010270 ret = -EINVAL;
10271 goto done;
10272 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010273 struct audio_patch *patch = p_info->patch;
10274 if (patch == NULL) {
10275 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010276 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010277 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010278 goto done;
10279 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010280 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10281 switch (patch->sources[0].type) {
10282 case AUDIO_PORT_TYPE_MIX:
10283 io_handle = patch->sources[0].ext.mix.handle;
10284 break;
10285 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010286 if (p_info->patch_type == PATCH_CAPTURE)
10287 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010288 break;
10289 case AUDIO_PORT_TYPE_SESSION:
10290 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010291 pthread_mutex_unlock(&adev->lock);
10292 ret = -EINVAL;
10293 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010294 }
10295
10296 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010297 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010298 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010299 if (patch_type == PATCH_PLAYBACK ||
10300 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010301 struct audio_stream_info *s_info =
10302 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10303 if (s_info == NULL) {
10304 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10305 pthread_mutex_unlock(&adev->lock);
10306 goto done;
10307 }
10308 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10309 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010310 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010311 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010312
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010313 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010314 struct listnode devices;
10315 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010316 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010317 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010318 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010319 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010320 }
10321
10322 if (ret < 0)
10323 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10324
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010325done:
10326 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10327 audio_extn_auto_hal_release_audio_patch(dev, handle);
10328
10329 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010330 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010331}
10332
10333int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10334{
Derek Chenf13dd492018-11-13 14:53:51 -080010335 int ret = 0;
10336
10337 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10338 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10339 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010340}
10341
10342int adev_set_audio_port_config(struct audio_hw_device *dev,
10343 const struct audio_port_config *config)
10344{
Derek Chenf13dd492018-11-13 14:53:51 -080010345 int ret = 0;
10346
10347 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10348 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10349 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010350}
10351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010352static int adev_dump(const audio_hw_device_t *device __unused,
10353 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010354{
10355 return 0;
10356}
10357
10358static int adev_close(hw_device_t *device)
10359{
Aalique Grahame22e49102018-12-18 14:23:57 -080010360 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010361 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010362
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010363 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010364 return 0;
10365
10366 pthread_mutex_lock(&adev_init_lock);
10367
10368 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010369 if (audio_extn_spkr_prot_is_enabled())
10370 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010371 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010372 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010373 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010374 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010375 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010376 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010377 audio_extn_utils_release_streams_cfg_lists(
10378 &adev->streams_output_cfg_list,
10379 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010380 if (audio_extn_qap_is_enabled())
10381 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010382 if (audio_extn_qaf_is_enabled())
10383 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010384 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010385 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010386 free(adev->snd_dev_ref_cnt);
10387 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010388 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10389 pcm_params_free(adev->use_case_table[i]);
10390 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010391 if (adev->adm_deinit)
10392 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010393 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010394 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010395 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010396 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010397 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010398 if (adev->device_cfg_params) {
10399 free(adev->device_cfg_params);
10400 adev->device_cfg_params = NULL;
10401 }
Derek Chend2530072014-11-24 12:39:14 -080010402 if(adev->ext_hw_plugin)
10403 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010404 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010405 free_map(adev->patch_map);
10406 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010407 free(device);
10408 adev = NULL;
10409 }
10410 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010411 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010412 return 0;
10413}
10414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010415/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10416 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10417 * just that it _might_ work.
10418 */
10419static int period_size_is_plausible_for_low_latency(int period_size)
10420{
10421 switch (period_size) {
10422 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010423 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010424 case 240:
10425 case 320:
10426 case 480:
10427 return 1;
10428 default:
10429 return 0;
10430 }
10431}
10432
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010433static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10434{
10435 bool is_snd_card_status = false;
10436 bool is_ext_device_status = false;
10437 char value[32];
10438 int card = -1;
10439 card_status_t status;
10440
10441 if (cookie != adev || !parms)
10442 return;
10443
10444 if (!parse_snd_card_status(parms, &card, &status)) {
10445 is_snd_card_status = true;
10446 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10447 is_ext_device_status = true;
10448 } else {
10449 // not a valid event
10450 return;
10451 }
10452
10453 pthread_mutex_lock(&adev->lock);
10454 if (card == adev->snd_card || is_ext_device_status) {
10455 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010456 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010457 adev->card_status = status;
10458 platform_snd_card_update(adev->platform, status);
10459 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010460 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010461 if (status == CARD_STATUS_OFFLINE)
10462 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010463 } else if (is_ext_device_status) {
10464 platform_set_parameters(adev->platform, parms);
10465 }
10466 }
10467 pthread_mutex_unlock(&adev->lock);
10468 return;
10469}
10470
Weiyin Jiang280ea742020-09-08 20:28:22 +080010471/* adev lock held */
10472int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010473{
10474 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010475 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010476 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010477 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010478
10479 uc_info = get_usecase_from_list(adev, out->usecase);
10480 if (uc_info == NULL) {
10481 ALOGE("%s: Could not find the usecase (%d) in the list",
10482 __func__, out->usecase);
10483 return -EINVAL;
10484 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010485 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010486
Zhou Songbaddf9f2020-11-20 13:57:39 +080010487 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10488 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010489
10490 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010491 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010492 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010493 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010494 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010495 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10496 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010497
10498 if (is_offload_usecase(out->usecase)) {
10499 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010500 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010501 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10502 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10503 } else {
10504 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010505 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010506 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010507 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010508 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010509 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010510 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010511 // mute stream and switch to speaker if suspended
10512 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010513 assign_devices(&devices, &out->device_list);
10514 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010515 list_for_each(node, &adev->usecase_list) {
10516 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010517 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10518 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010519 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010520 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10521 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010522 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10523 break;
10524 }
10525 }
Zhou Songcf77af02021-05-14 18:21:14 +080010526 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10527 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010528 out->a2dp_muted = true;
10529 if (is_offload_usecase(out->usecase)) {
10530 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10531 compress_pause(out->compr);
10532 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010533 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010534 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10535 out_set_voip_volume(&out->stream, (float)0, (float)0);
10536 else
10537 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10538
Zhou Song8edbbdb2021-01-14 16:48:03 +080010539 /* wait for stale pcm drained before switching to speaker */
10540 uint32_t latency =
10541 (out->config.period_count * out->config.period_size * 1000) /
10542 (out->config.rate);
10543 usleep(latency * 1000);
10544 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010545 }
10546 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010547 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10548 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010549 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010550 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10551 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010552 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010553 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010554 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010555 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010556 }
10557 ALOGV("%s: exit", __func__);
10558 return 0;
10559}
10560
Haynes Mathew George01156f92018-04-13 15:29:54 -070010561void adev_on_battery_status_changed(bool charging)
10562{
10563 pthread_mutex_lock(&adev->lock);
10564 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10565 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010566 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010567 pthread_mutex_unlock(&adev->lock);
10568}
10569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010570static int adev_open(const hw_module_t *module, const char *name,
10571 hw_device_t **device)
10572{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010573 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010574 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010575 char mixer_ctl_name[128] = {0};
10576 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010577
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010578 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010579 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10580
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010581 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010582 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010583 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010584 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010585 ALOGD("%s: returning existing instance of adev", __func__);
10586 ALOGD("%s: exit", __func__);
10587 pthread_mutex_unlock(&adev_init_lock);
10588 return 0;
10589 }
10590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010591 adev = calloc(1, sizeof(struct audio_device));
10592
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010593 if (!adev) {
10594 pthread_mutex_unlock(&adev_init_lock);
10595 return -ENOMEM;
10596 }
10597
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010598 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10599
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010600 // register audio ext hidl at the earliest
10601 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010602#ifdef DYNAMIC_LOG_ENABLED
10603 register_for_dynamic_logging("hal");
10604#endif
10605
Derek Chenf939fb72018-11-13 13:34:41 -080010606 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010607 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010608 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10609 maj_version = atoi(value);
10610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010611 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010612 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010613 adev->device.common.module = (struct hw_module_t *)module;
10614 adev->device.common.close = adev_close;
10615
10616 adev->device.init_check = adev_init_check;
10617 adev->device.set_voice_volume = adev_set_voice_volume;
10618 adev->device.set_master_volume = adev_set_master_volume;
10619 adev->device.get_master_volume = adev_get_master_volume;
10620 adev->device.set_master_mute = adev_set_master_mute;
10621 adev->device.get_master_mute = adev_get_master_mute;
10622 adev->device.set_mode = adev_set_mode;
10623 adev->device.set_mic_mute = adev_set_mic_mute;
10624 adev->device.get_mic_mute = adev_get_mic_mute;
10625 adev->device.set_parameters = adev_set_parameters;
10626 adev->device.get_parameters = adev_get_parameters;
10627 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10628 adev->device.open_output_stream = adev_open_output_stream;
10629 adev->device.close_output_stream = adev_close_output_stream;
10630 adev->device.open_input_stream = adev_open_input_stream;
10631 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010632 adev->device.create_audio_patch = adev_create_audio_patch;
10633 adev->device.release_audio_patch = adev_release_audio_patch;
10634 adev->device.get_audio_port = adev_get_audio_port;
10635 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010636 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010637 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010638
10639 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010640 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010641 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010642 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010643 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010644 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010645 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010646 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010647 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010648 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010649 /* Init audio and voice feature */
10650 audio_extn_feature_init();
10651 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010652 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010653 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010654 list_init(&adev->active_inputs_list);
10655 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010656 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010657 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10658 audio_extn_utils_hash_eq);
10659 if (!adev->io_streams_map) {
10660 ALOGE("%s: Could not create io streams map", __func__);
10661 ret = -ENOMEM;
10662 goto adev_open_err;
10663 }
10664 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10665 audio_extn_utils_hash_eq);
10666 if (!adev->patch_map) {
10667 ALOGE("%s: Could not create audio patch map", __func__);
10668 ret = -ENOMEM;
10669 goto adev_open_err;
10670 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010671 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010672 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010673 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010674 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010675 adev->perf_lock_opts[0] = 0x101;
10676 adev->perf_lock_opts[1] = 0x20E;
10677 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010678 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010679 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010680 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010681 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010682 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010683
Zhou Song68ebc352019-12-05 17:11:15 +080010684 audio_extn_perf_lock_init();
10685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010686 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010687 adev->platform = platform_init(adev);
10688 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010689 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010690 ret = -EINVAL;
10691 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010692 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010693
Aalique Grahame22e49102018-12-18 14:23:57 -080010694 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010695 if (audio_extn_qap_is_enabled()) {
10696 ret = audio_extn_qap_init(adev);
10697 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010698 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010699 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010700 }
10701 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10702 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10703 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010704
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010705 if (audio_extn_qaf_is_enabled()) {
10706 ret = audio_extn_qaf_init(adev);
10707 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010708 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010709 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010710 }
10711
10712 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10713 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10714 }
10715
Derek Chenae7b0342019-02-08 15:17:04 -080010716 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010717 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10718
Eric Laurentc4aef752013-09-12 17:45:53 -070010719 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10720 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10721 if (adev->visualizer_lib == NULL) {
10722 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10723 } else {
10724 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10725 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010726 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010727 "visualizer_hal_start_output");
10728 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010729 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010730 "visualizer_hal_stop_output");
10731 }
10732 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010733 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010734 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010735 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010736 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010737 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010738 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010739
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010740 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10741 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10742 if (adev->offload_effects_lib == NULL) {
10743 ALOGE("%s: DLOPEN failed for %s", __func__,
10744 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10745 } else {
10746 ALOGV("%s: DLOPEN successful for %s", __func__,
10747 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10748 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010749 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010750 "offload_effects_bundle_hal_start_output");
10751 adev->offload_effects_stop_output =
10752 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10753 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010754 adev->offload_effects_set_hpx_state =
10755 (int (*)(bool))dlsym(adev->offload_effects_lib,
10756 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010757 adev->offload_effects_get_parameters =
10758 (void (*)(struct str_parms *, struct str_parms *))
10759 dlsym(adev->offload_effects_lib,
10760 "offload_effects_bundle_get_parameters");
10761 adev->offload_effects_set_parameters =
10762 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10763 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010764 }
10765 }
10766
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010767 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10768 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10769 if (adev->adm_lib == NULL) {
10770 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10771 } else {
10772 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10773 adev->adm_init = (adm_init_t)
10774 dlsym(adev->adm_lib, "adm_init");
10775 adev->adm_deinit = (adm_deinit_t)
10776 dlsym(adev->adm_lib, "adm_deinit");
10777 adev->adm_register_input_stream = (adm_register_input_stream_t)
10778 dlsym(adev->adm_lib, "adm_register_input_stream");
10779 adev->adm_register_output_stream = (adm_register_output_stream_t)
10780 dlsym(adev->adm_lib, "adm_register_output_stream");
10781 adev->adm_deregister_stream = (adm_deregister_stream_t)
10782 dlsym(adev->adm_lib, "adm_deregister_stream");
10783 adev->adm_request_focus = (adm_request_focus_t)
10784 dlsym(adev->adm_lib, "adm_request_focus");
10785 adev->adm_abandon_focus = (adm_abandon_focus_t)
10786 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010787 adev->adm_set_config = (adm_set_config_t)
10788 dlsym(adev->adm_lib, "adm_set_config");
10789 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10790 dlsym(adev->adm_lib, "adm_request_focus_v2");
10791 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10792 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10793 adev->adm_on_routing_change = (adm_on_routing_change_t)
10794 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010795 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10796 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010797 }
10798 }
10799
Aalique Grahame22e49102018-12-18 14:23:57 -080010800 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010801 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010802 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080010803 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010804 //initialize this to false for now,
10805 //this will be set to true through set param
10806 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010807
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010808 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010809 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010810
10811 if (k_enable_extended_precision)
10812 adev_verify_devices(adev);
10813
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010814 adev->dsp_bit_width_enforce_mode =
10815 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010816
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010817 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10818 &adev->streams_output_cfg_list,
10819 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010820
Kiran Kandi910e1862013-10-29 13:29:42 -070010821 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010822
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010823 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010824 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010825 trial = atoi(value);
10826 if (period_size_is_plausible_for_low_latency(trial)) {
10827 pcm_config_low_latency.period_size = trial;
10828 pcm_config_low_latency.start_threshold = trial / 4;
10829 pcm_config_low_latency.avail_min = trial / 4;
10830 configured_low_latency_capture_period_size = trial;
10831 }
10832 }
ronghuiz93177262021-04-21 19:58:13 +080010833 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010834 trial = atoi(value);
10835 if (period_size_is_plausible_for_low_latency(trial)) {
10836 configured_low_latency_capture_period_size = trial;
10837 }
10838 }
10839
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010840 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10841
Eric Laurent4b084132018-10-19 17:33:43 -070010842 adev->camera_orientation = CAMERA_DEFAULT;
10843
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010844 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010845 af_period_multiplier = atoi(value);
10846 if (af_period_multiplier < 0)
10847 af_period_multiplier = 2;
10848 else if (af_period_multiplier > 4)
10849 af_period_multiplier = 4;
10850
10851 ALOGV("new period_multiplier = %d", af_period_multiplier);
10852 }
10853
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010854 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010855
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010856 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010857 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010858 pthread_mutex_unlock(&adev_init_lock);
10859
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010860 if (adev->adm_init)
10861 adev->adm_data = adev->adm_init();
10862
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010863 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010864 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010865
10866 audio_extn_snd_mon_init();
10867 pthread_mutex_lock(&adev->lock);
10868 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10869 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010870 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10871 /*
10872 * if the battery state callback happens before charging can be queried,
10873 * it will be guarded with the adev->lock held in the cb function and so
10874 * the callback value will reflect the latest state
10875 */
10876 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010877 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010878 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010879 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010880 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010881 /* Allocate memory for Device config params */
10882 adev->device_cfg_params = (struct audio_device_config_param*)
10883 calloc(platform_get_max_codec_backend(),
10884 sizeof(struct audio_device_config_param));
10885 if (adev->device_cfg_params == NULL)
10886 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010887
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010888 /*
10889 * Check if new PSPD matrix mixer control is supported. If not
10890 * supported, then set flag so that old mixer ctrl is sent while
10891 * sending pspd coefficients on older kernel version. Query mixer
10892 * control for default pcm id and channel value one.
10893 */
10894 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10895 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10896
10897 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10898 if (!ctl) {
10899 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10900 __func__, mixer_ctl_name);
10901 adev->use_old_pspd_mix_ctrl = true;
10902 }
10903
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010904 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010905 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010906
10907adev_open_err:
10908 free_map(adev->patch_map);
10909 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010910 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010911 pthread_mutex_destroy(&adev->lock);
10912 free(adev);
10913 adev = NULL;
10914 *device = NULL;
10915 pthread_mutex_unlock(&adev_init_lock);
10916 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010917}
10918
10919static struct hw_module_methods_t hal_module_methods = {
10920 .open = adev_open,
10921};
10922
10923struct audio_module HAL_MODULE_INFO_SYM = {
10924 .common = {
10925 .tag = HARDWARE_MODULE_TAG,
10926 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10927 .hal_api_version = HARDWARE_HAL_API_VERSION,
10928 .id = AUDIO_HARDWARE_MODULE_ID,
10929 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010930 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010931 .methods = &hal_module_methods,
10932 },
10933};