blob: 7a66ea4e47830d46e1fef5f8bc67624cdb74c8ef [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Zhou Song642ec432020-12-23 16:11:10 +08002 * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Songbaddf9f2020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700151static unsigned int configured_low_latency_capture_period_size =
152 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
153
Haynes Mathew George16081042017-05-31 17:16:49 -0700154#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
155#define MMAP_PERIOD_COUNT_MIN 32
156#define MMAP_PERIOD_COUNT_MAX 512
157#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
158
Aalique Grahame22e49102018-12-18 14:23:57 -0800159/* This constant enables extended precision handling.
160 * TODO The flag is off until more testing is done.
161 */
162static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700163extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800164
Eric Laurentb23d5282013-05-14 15:27:20 -0700165struct pcm_config pcm_config_deep_buffer = {
166 .channels = 2,
167 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
168 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
169 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
172 .stop_threshold = INT_MAX,
173 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
174};
175
176struct pcm_config pcm_config_low_latency = {
177 .channels = 2,
178 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
179 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
180 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
183 .stop_threshold = INT_MAX,
184 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185};
186
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800187struct pcm_config pcm_config_haptics_audio = {
188 .channels = 1,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
191 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
194 .stop_threshold = INT_MAX,
195 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
196};
197
198struct pcm_config pcm_config_haptics = {
199 .channels = 1,
200 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
201 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
202 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
203 .format = PCM_FORMAT_S16_LE,
204 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .stop_threshold = INT_MAX,
206 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209static int af_period_multiplier = 4;
210struct pcm_config pcm_config_rt = {
211 .channels = 2,
212 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
213 .period_size = ULL_PERIOD_SIZE, //1 ms
214 .period_count = 512, //=> buffer size is 512ms
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
217 .stop_threshold = INT_MAX,
218 .silence_threshold = 0,
219 .silence_size = 0,
220 .avail_min = ULL_PERIOD_SIZE, //1 ms
221};
222
Eric Laurentb23d5282013-05-14 15:27:20 -0700223struct pcm_config pcm_config_hdmi_multi = {
224 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
225 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
226 .period_size = HDMI_MULTI_PERIOD_SIZE,
227 .period_count = HDMI_MULTI_PERIOD_COUNT,
228 .format = PCM_FORMAT_S16_LE,
229 .start_threshold = 0,
230 .stop_threshold = INT_MAX,
231 .avail_min = 0,
232};
233
Haynes Mathew George16081042017-05-31 17:16:49 -0700234struct pcm_config pcm_config_mmap_playback = {
235 .channels = 2,
236 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
237 .period_size = MMAP_PERIOD_SIZE,
238 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
239 .format = PCM_FORMAT_S16_LE,
240 .start_threshold = MMAP_PERIOD_SIZE*8,
241 .stop_threshold = INT32_MAX,
242 .silence_threshold = 0,
243 .silence_size = 0,
244 .avail_min = MMAP_PERIOD_SIZE, //1 ms
245};
246
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700247struct pcm_config pcm_config_hifi = {
248 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
249 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
250 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
251 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
252 .format = PCM_FORMAT_S24_3LE,
253 .start_threshold = 0,
254 .stop_threshold = INT_MAX,
255 .avail_min = 0,
256};
257
Eric Laurentb23d5282013-05-14 15:27:20 -0700258struct pcm_config pcm_config_audio_capture = {
259 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
261 .format = PCM_FORMAT_S16_LE,
262};
263
Haynes Mathew George16081042017-05-31 17:16:49 -0700264struct pcm_config pcm_config_mmap_capture = {
265 .channels = 2,
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
267 .period_size = MMAP_PERIOD_SIZE,
268 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
269 .format = PCM_FORMAT_S16_LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .silence_threshold = 0,
273 .silence_size = 0,
274 .avail_min = MMAP_PERIOD_SIZE, //1 ms
275};
276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700277#define AFE_PROXY_CHANNEL_COUNT 2
278#define AFE_PROXY_SAMPLING_RATE 48000
279
280#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
281#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
282
283struct pcm_config pcm_config_afe_proxy_playback = {
284 .channels = AFE_PROXY_CHANNEL_COUNT,
285 .rate = AFE_PROXY_SAMPLING_RATE,
286 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
287 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
288 .format = PCM_FORMAT_S16_LE,
289 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
290 .stop_threshold = INT_MAX,
291 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
292};
293
294#define AFE_PROXY_RECORD_PERIOD_SIZE 768
295#define AFE_PROXY_RECORD_PERIOD_COUNT 4
296
Aalique Grahame22e49102018-12-18 14:23:57 -0800297struct pcm_config pcm_config_audio_capture_rt = {
298 .channels = 2,
299 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
300 .period_size = ULL_PERIOD_SIZE,
301 .period_count = 512,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = 0,
304 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
305 .silence_threshold = 0,
306 .silence_size = 0,
307 .avail_min = ULL_PERIOD_SIZE, //1 ms
308};
309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700310struct pcm_config pcm_config_afe_proxy_record = {
311 .channels = AFE_PROXY_CHANNEL_COUNT,
312 .rate = AFE_PROXY_SAMPLING_RATE,
313 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
314 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
315 .format = PCM_FORMAT_S16_LE,
316 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
317 .stop_threshold = INT_MAX,
318 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
319};
320
Ashish Jainf1eaa582016-05-23 20:54:24 +0530321#define AUDIO_MAX_PCM_FORMATS 7
322
323const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
324 [AUDIO_FORMAT_DEFAULT] = 0,
325 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
326 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
327 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
329 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
330 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
331};
332
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800333const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700334 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
335 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800336 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800337 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700338 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
339 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700340 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700341 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
349 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700350 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
351 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700352 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800353 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700354
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700356 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530357 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
358 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
359 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530360 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
361 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700363 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700364 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700365 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700366
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800367 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800368 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400369 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
370 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700371
Derek Chenf7092792017-05-23 12:23:53 -0400372 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700373 [USECASE_VOICE2_CALL] = "voice2-call",
374 [USECASE_VOLTE_CALL] = "volte-call",
375 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800376 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800377 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
378 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800379 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700380 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
381 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
382 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800383 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
384 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
385 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
386
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700387 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
388 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700389 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
390 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700391
392 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
393 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800394 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530395 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700396
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530397 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
399 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700400
401 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
402 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530403 [USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY] = "audio-record-voip-low-latency",
Varun Balaraje49253e2017-07-06 19:48:56 +0530404 /* For Interactive Audio Streams */
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
412 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700413
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800414 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
415
Derek Chenf6318be2017-06-12 17:16:24 -0400416 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
417
418 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
419 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
420 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
421 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800422 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700423 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530424 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Derek Chena30a5f42019-12-03 11:17:09 -0500425 [USECASE_ICC_CALL] = "icc-call",
Huicheng Liu1404ba12020-09-11 01:03:25 -0400426
427 [USECASE_AUDIO_RECORD_BUS] = "audio-record",
428 [USECASE_AUDIO_RECORD_BUS_FRONT_PASSENGER] = "front-passenger-record",
429 [USECASE_AUDIO_RECORD_BUS_REAR_SEAT] = "rear-seat-record",
Fei Tongaffdf732020-02-20 20:39:05 +0800430 [USECASE_AUDIO_PLAYBACK_SYNTHESIZER] = "synth-loopback",
Susan Wange3959562021-03-11 11:50:26 -0500431 [USECASE_AUDIO_RECORD_ECHO_REF_EXT] = "echo-reference-external",
Eric Laurentb23d5282013-05-14 15:27:20 -0700432};
433
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700434static const audio_usecase_t offload_usecases[] = {
435 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
437 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
438 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
439 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
440 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
441 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
442 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
443 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700444};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445
Varun Balaraje49253e2017-07-06 19:48:56 +0530446static const audio_usecase_t interactive_usecases[] = {
447 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
448 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
449 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
450 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
451 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
452 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
453 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
454 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
455};
456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457#define STRING_TO_ENUM(string) { #string, string }
458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800459struct string_to_enum {
460 const char *name;
461 uint32_t value;
462};
463
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800465 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800466 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
467 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
468 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700469 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800470 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
471 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800472 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700473 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
474 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
475 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
476 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
477 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
478 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
479 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
480 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
481 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
482 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
483 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum formats_name_to_enum_table[] = {
487 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
488 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
489 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700490 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
491 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
492 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700493 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800494 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
495 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700496 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800497};
498
499//list of all supported sample rates by HDMI specification.
500static const int out_hdmi_sample_rates[] = {
501 32000, 44100, 48000, 88200, 96000, 176400, 192000,
502};
503
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700504static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800505 STRING_TO_ENUM(32000),
506 STRING_TO_ENUM(44100),
507 STRING_TO_ENUM(48000),
508 STRING_TO_ENUM(88200),
509 STRING_TO_ENUM(96000),
510 STRING_TO_ENUM(176400),
511 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800512 STRING_TO_ENUM(352800),
513 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700514};
515
Carter Hsu2e429db2019-05-14 18:50:52 +0800516struct in_effect_list {
517 struct listnode list;
518 effect_handle_t handle;
519};
520
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700521static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700522static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700523static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700524//cache last MBDRC cal step level
525static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700526
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530527static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700528static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800529static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530530static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530531
Derek Chen6f293672019-04-01 01:40:24 -0700532static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
533static void in_snd_mon_cb(void * stream, struct str_parms * parms);
534static void out_snd_mon_cb(void * stream, struct str_parms * parms);
535
Zhou Song331c8e52019-08-26 14:16:12 +0800536static int configure_btsco_sample_rate(snd_device_t snd_device);
537
Vatsal Buchac09ae062018-11-14 13:25:08 +0530538#ifdef AUDIO_FEATURE_ENABLED_GCOV
539extern void __gcov_flush();
540static void enable_gcov()
541{
542 __gcov_flush();
543}
544#else
545static void enable_gcov()
546{
547}
548#endif
549
justinweng20fb6d82019-02-21 18:49:00 -0700550static int in_set_microphone_direction(const struct audio_stream_in *stream,
551 audio_microphone_direction_t dir);
552static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
553
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700554static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
555 int flags __unused)
556{
557 int dir = 0;
558 switch (uc_id) {
559 case USECASE_AUDIO_RECORD_LOW_LATENCY:
Revathi Uddarajud9f23d92020-07-27 10:55:06 +0530560 case USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY:
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700561 dir = 1;
562 case USECASE_AUDIO_PLAYBACK_ULL:
563 break;
564 default:
565 return false;
566 }
567
568 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
569 PCM_PLAYBACK : PCM_CAPTURE);
570 if (adev->adm_is_noirq_avail)
571 return adev->adm_is_noirq_avail(adev->adm_data,
572 adev->snd_card, dev_id, dir);
573 return false;
574}
575
576static void register_out_stream(struct stream_out *out)
577{
578 struct audio_device *adev = out->dev;
579 if (is_offload_usecase(out->usecase) ||
580 !adev->adm_register_output_stream)
581 return;
582
583 // register stream first for backward compatibility
584 adev->adm_register_output_stream(adev->adm_data,
585 out->handle,
586 out->flags);
587
588 if (!adev->adm_set_config)
589 return;
590
591 if (out->realtime)
592 adev->adm_set_config(adev->adm_data,
593 out->handle,
594 out->pcm, &out->config);
595}
596
597static void register_in_stream(struct stream_in *in)
598{
599 struct audio_device *adev = in->dev;
600 if (!adev->adm_register_input_stream)
601 return;
602
603 adev->adm_register_input_stream(adev->adm_data,
604 in->capture_handle,
605 in->flags);
606
607 if (!adev->adm_set_config)
608 return;
609
610 if (in->realtime)
611 adev->adm_set_config(adev->adm_data,
612 in->capture_handle,
613 in->pcm,
614 &in->config);
615}
616
617static void request_out_focus(struct stream_out *out, long ns)
618{
619 struct audio_device *adev = out->dev;
620
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 if (adev->adm_request_focus_v2)
622 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
623 else if (adev->adm_request_focus)
624 adev->adm_request_focus(adev->adm_data, out->handle);
625}
626
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700627static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700628{
629 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700630 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700632 if (adev->adm_request_focus_v2_1)
633 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
634 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700635 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
636 else if (adev->adm_request_focus)
637 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700638
639 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700640}
641
642static void release_out_focus(struct stream_out *out)
643{
644 struct audio_device *adev = out->dev;
645
646 if (adev->adm_abandon_focus)
647 adev->adm_abandon_focus(adev->adm_data, out->handle);
648}
649
650static void release_in_focus(struct stream_in *in)
651{
652 struct audio_device *adev = in->dev;
653 if (adev->adm_abandon_focus)
654 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
655}
656
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530657static int parse_snd_card_status(struct str_parms *parms, int *card,
658 card_status_t *status)
659{
660 char value[32]={0};
661 char state[32]={0};
662
663 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
664 if (ret < 0)
665 return -1;
666
667 // sscanf should be okay as value is of max length 32.
668 // same as sizeof state.
669 if (sscanf(value, "%d,%s", card, state) < 2)
670 return -1;
671
672 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
673 CARD_STATUS_OFFLINE;
674 return 0;
675}
676
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700677static inline void adjust_frames_for_device_delay(struct stream_out *out,
678 uint32_t *dsp_frames) {
679 // Adjustment accounts for A2dp encoder latency with offload usecases
680 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800681 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700682 unsigned long offset =
683 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
684 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
685 }
686}
687
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700688static inline bool free_entry(void *key __unused,
689 void *value, void *context __unused)
690{
691 free(value);
692 return true;
693}
694
695static inline void free_map(Hashmap *map)
696{
697 if (map) {
698 hashmapForEach(map, free_entry, (void *) NULL);
699 hashmapFree(map);
700 }
701}
702
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800703static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700704 audio_patch_handle_t patch_handle)
705{
706 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
707 return;
708
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700709 struct audio_patch_info *p_info =
710 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
711 if (p_info) {
712 ALOGV("%s: Remove patch %d", __func__, patch_handle);
713 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
714 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715 free(p_info);
716 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700717}
718
719static inline int io_streams_map_insert(struct audio_device *adev,
720 struct audio_stream *stream,
721 audio_io_handle_t handle,
722 audio_patch_handle_t patch_handle)
723{
724 struct audio_stream_info *s_info =
725 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
726
727 if (s_info == NULL) {
728 ALOGE("%s: Could not allocate stream info", __func__);
729 return -ENOMEM;
730 }
731 s_info->stream = stream;
732 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700733
734 pthread_mutex_lock(&adev->lock);
735 struct audio_stream_info *stream_info =
736 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700737 if (stream_info != NULL)
738 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700740 ALOGV("%s: Added stream in io_streams_map with handle %d", __func__, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 return 0;
742}
743
744static inline void io_streams_map_remove(struct audio_device *adev,
745 audio_io_handle_t handle)
746{
747 pthread_mutex_lock(&adev->lock);
748 struct audio_stream_info *s_info =
749 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751 goto done;
Aniket Kumar Latad13758f2020-08-06 15:11:36 -0700752 ALOGV("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800753 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700754 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800755done:
756 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return;
758}
759
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800760static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700761 audio_patch_handle_t handle)
762{
763 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700764 p_info = (struct audio_patch_info *)
765 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700766 return p_info;
767}
768
vivek mehtaa76401a2015-04-24 14:12:15 -0700769__attribute__ ((visibility ("default")))
770bool audio_hw_send_gain_dep_calibration(int level) {
771 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700772 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700773
774 pthread_mutex_lock(&adev_init_lock);
775
776 if (adev != NULL && adev->platform != NULL) {
777 pthread_mutex_lock(&adev->lock);
778 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700779
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530780 // cache level info for any of the use case which
781 // was not started.
782 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700783
vivek mehtaa76401a2015-04-24 14:12:15 -0700784 pthread_mutex_unlock(&adev->lock);
785 } else {
786 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
787 }
788
789 pthread_mutex_unlock(&adev_init_lock);
790
791 return ret_val;
792}
793
Ashish Jain5106d362016-05-11 19:23:33 +0530794static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
795{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796 bool gapless_enabled = false;
797 const char *mixer_ctl_name = "Compress Gapless Playback";
798 struct mixer_ctl *ctl;
799
800 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700801 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530802
803 /*Disable gapless if its AV playback*/
804 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800805
806 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
807 if (!ctl) {
808 ALOGE("%s: Could not get ctl for mixer cmd - %s",
809 __func__, mixer_ctl_name);
810 return -EINVAL;
811 }
812
813 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
814 ALOGE("%s: Could not set gapless mode %d",
815 __func__, gapless_enabled);
816 return -EINVAL;
817 }
818 return 0;
819}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700820
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700821__attribute__ ((visibility ("default")))
822int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
823 int table_size) {
824 int ret_val = 0;
825 ALOGV("%s: enter ... ", __func__);
826
827 pthread_mutex_lock(&adev_init_lock);
828 if (adev == NULL) {
829 ALOGW("%s: adev is NULL .... ", __func__);
830 goto done;
831 }
832
833 pthread_mutex_lock(&adev->lock);
834 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
835 pthread_mutex_unlock(&adev->lock);
836done:
837 pthread_mutex_unlock(&adev_init_lock);
838 ALOGV("%s: exit ... ", __func__);
839 return ret_val;
840}
841
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800843{
844 bool ret = false;
845 ALOGV("%s: enter ...", __func__);
846
847 pthread_mutex_lock(&adev_init_lock);
848
849 if (adev != NULL && adev->platform != NULL) {
850 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800851 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800852 pthread_mutex_unlock(&adev->lock);
853 }
854
855 pthread_mutex_unlock(&adev_init_lock);
856
857 ALOGV("%s: exit with ret %d", __func__, ret);
858 return ret;
859}
Aalique Grahame22e49102018-12-18 14:23:57 -0800860
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700861static bool is_supported_format(audio_format_t format)
862{
Eric Laurent86e17132013-09-12 17:49:30 -0700863 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530864 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530865 format == AUDIO_FORMAT_AAC_LC ||
866 format == AUDIO_FORMAT_AAC_HE_V1 ||
867 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530868 format == AUDIO_FORMAT_AAC_ADTS_LC ||
869 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
870 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530871 format == AUDIO_FORMAT_AAC_LATM_LC ||
872 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
873 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530874 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
875 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530876 format == AUDIO_FORMAT_PCM_FLOAT ||
877 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700878 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530879 format == AUDIO_FORMAT_AC3 ||
880 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700881 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530882 format == AUDIO_FORMAT_DTS ||
883 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800884 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530885 format == AUDIO_FORMAT_ALAC ||
886 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530887 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530888 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800889 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530890 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700891 format == AUDIO_FORMAT_APTX ||
892 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800893 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700894
895 return false;
896}
897
Kunlei Zhang67cc7072020-12-18 17:16:49 +0800898static bool is_supported_conc_usecase_for_power_mode_call(struct audio_device *adev)
899{
900 struct listnode *node;
901 struct audio_usecase *usecase;
902
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
905 if (usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
906 ALOGD("%s: FM usecase is active, not setting power mode", __func__);
907 return false;
908 }
909 }
910
911 return true;
912}
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700913static inline bool is_mmap_usecase(audio_usecase_t uc_id)
914{
915 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800916 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700917 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
918}
919
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700920static inline bool is_valid_volume(float left, float right)
921{
922 return ((left >= 0.0f && right >= 0.0f) ? true : false);
923}
924
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530925static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530926{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530927 ALOGV("%s", __func__);
928 audio_route_apply_and_update_path(adev->audio_route,
929 "asrc-mode");
930 adev->asrc_mode_enabled = true;
931}
932
933static void disable_asrc_mode(struct audio_device *adev)
934{
935 ALOGV("%s", __func__);
936 audio_route_reset_and_update_path(adev->audio_route,
937 "asrc-mode");
938 adev->asrc_mode_enabled = false;
939}
940
Saurav Kumarc1411662020-10-14 10:50:45 +0530941static void check_and_configure_headphone(struct audio_device *adev,
942 struct audio_usecase *uc_info,
943 snd_device_t snd_device)
944{
945 struct listnode *node;
946 struct audio_usecase *usecase;
947 int new_backend_idx, usecase_backend_idx;
948 bool spkr_hph_single_be_native_concurrency;
949
950 new_backend_idx = platform_get_backend_index(snd_device);
951 spkr_hph_single_be_native_concurrency = platform_get_spkr_hph_single_be_native_concurrency_flag();
Zhou Songd4b18c42021-01-14 15:15:29 +0800952 if ((spkr_hph_single_be_native_concurrency && (new_backend_idx == DEFAULT_CODEC_BACKEND)) ||
953 uc_info->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
Saurav Kumarc1411662020-10-14 10:50:45 +0530954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
957 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
958 if (((usecase_backend_idx == HEADPHONE_BACKEND) ||
959 (usecase_backend_idx == HEADPHONE_44_1_BACKEND)) &&
960 ((usecase->stream.out->sample_rate % OUTPUT_SAMPLING_RATE_44100) == 0)) {
961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->out_snd_device);
963 usecase->stream.out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Saurav Kumar70902382020-10-28 11:16:04 +0530964 platform_check_and_set_codec_backend_cfg(adev, usecase,
965 usecase->out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +0530966 enable_snd_device(adev, usecase->out_snd_device);
Zhou Songd4b18c42021-01-14 15:15:29 +0800967 enable_audio_route(adev, usecase);
Saurav Kumarc1411662020-10-14 10:50:45 +0530968 }
969 }
970 }
971 }
972}
973
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530974/*
975 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
976 * 44.1 or Native DSD backends are enabled for any of current use case.
977 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
978 * - Disable current mix path use case(Headphone backend) and re-enable it with
979 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
980 * e.g. Naitve DSD or Headphone 44.1 -> + 48
981 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530982static void check_and_set_asrc_mode(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530985{
986 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530987 int i, num_new_devices = 0;
988 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
989 /*
990 *Split snd device for new combo use case
991 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
992 */
993 if (platform_split_snd_device(adev->platform,
994 snd_device,
995 &num_new_devices,
996 split_new_snd_devices) == 0) {
997 for (i = 0; i < num_new_devices; i++)
998 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
999 } else {
1000 int new_backend_idx = platform_get_backend_index(snd_device);
1001 if (((new_backend_idx == HEADPHONE_BACKEND) ||
1002 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1003 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1004 !adev->asrc_mode_enabled) {
1005 struct listnode *node = NULL;
1006 struct audio_usecase *uc = NULL;
1007 struct stream_out *curr_out = NULL;
1008 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
1009 int i, num_devices, ret = 0;
1010 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301011
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301012 list_for_each(node, &adev->usecase_list) {
1013 uc = node_to_item(node, struct audio_usecase, list);
1014 curr_out = (struct stream_out*) uc->stream.out;
1015 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
1016 /*
1017 *Split snd device for existing combo use case
1018 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
1019 */
1020 ret = platform_split_snd_device(adev->platform,
1021 uc->out_snd_device,
1022 &num_devices,
1023 split_snd_devices);
1024 if (ret < 0 || num_devices == 0) {
1025 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
1026 split_snd_devices[0] = uc->out_snd_device;
1027 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -08001028 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301029 for (i = 0; i < num_devices; i++) {
1030 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
1031 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
1032 if((new_backend_idx == HEADPHONE_BACKEND) &&
1033 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
1034 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001035 ALOGV("%s:DSD or native stream detected enabling asrcmode in hardware",
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301036 __func__);
1037 enable_asrc_mode(adev);
1038 break;
1039 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
1040 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
1041 (usecase_backend_idx == HEADPHONE_BACKEND)) {
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07001042 ALOGV("%s: 48K stream detected, disabling and enabling it \
1043 with asrcmode in hardware", __func__);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301044 disable_audio_route(adev, uc);
1045 disable_snd_device(adev, uc->out_snd_device);
1046 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1047 if (new_backend_idx == DSD_NATIVE_BACKEND)
1048 audio_route_apply_and_update_path(adev->audio_route,
1049 "hph-true-highquality-mode");
1050 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1051 (curr_out->bit_width >= 24))
1052 audio_route_apply_and_update_path(adev->audio_route,
1053 "hph-highquality-mode");
1054 enable_asrc_mode(adev);
1055 enable_snd_device(adev, uc->out_snd_device);
1056 enable_audio_route(adev, uc);
1057 break;
1058 }
1059 }
1060 // reset split devices count
1061 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001062 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301063 if (adev->asrc_mode_enabled)
1064 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301065 }
1066 }
1067 }
1068}
1069
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001070static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1071 struct audio_effect_config effect_config,
1072 unsigned int param_value)
1073{
1074 char mixer_ctl_name[] = "Audio Effect";
1075 struct mixer_ctl *ctl;
1076 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001077 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001078
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001079 if (in == NULL) {
1080 ALOGE("%s: active input stream is NULL", __func__);
1081 return -EINVAL;
1082 }
1083
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001084 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1085 if (!ctl) {
1086 ALOGE("%s: Could not get mixer ctl - %s",
1087 __func__, mixer_ctl_name);
1088 return -EINVAL;
1089 }
1090
1091 set_values[0] = 1; //0:Rx 1:Tx
1092 set_values[1] = in->app_type_cfg.app_type;
1093 set_values[2] = (long)effect_config.module_id;
1094 set_values[3] = (long)effect_config.instance_id;
1095 set_values[4] = (long)effect_config.param_id;
1096 set_values[5] = param_value;
1097
1098 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1099
1100 return 0;
1101
1102}
1103
1104static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1105 int effect_type, unsigned int *param_value)
1106{
1107 int ret = 0;
1108 struct audio_effect_config other_effect_config;
1109 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001110 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001111
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001112 if (in == NULL) {
1113 ALOGE("%s: active input stream is NULL", __func__);
1114 return -EINVAL;
1115 }
1116
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001117 usecase = get_usecase_from_list(adev, in->usecase);
1118 if (!usecase)
1119 return -EINVAL;
1120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1122 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1123 if (ret < 0) {
1124 ALOGE("%s Failed to get effect params %d", __func__, ret);
1125 return ret;
1126 }
1127
1128 if (module_id == other_effect_config.module_id) {
1129 //Same module id for AEC/NS. Values need to be combined
1130 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1131 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1132 *param_value |= other_effect_config.param_value;
1133 }
1134 }
1135
1136 return ret;
1137}
1138
1139static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301140{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001141 struct audio_effect_config effect_config;
1142 struct audio_usecase *usecase = NULL;
1143 int ret = 0;
1144 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001145 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001146
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001147 if(!voice_extn_is_dynamic_ecns_enabled())
1148 return ENOSYS;
1149
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150 if (!in) {
1151 ALOGE("%s: Invalid input stream", __func__);
1152 return -EINVAL;
1153 }
1154
1155 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1156
1157 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001158 if (usecase == NULL) {
1159 ALOGE("%s: Could not find the usecase (%d) in the list",
1160 __func__, in->usecase);
1161 return -EINVAL;
1162 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
1164 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1165 if (ret < 0) {
1166 ALOGE("%s Failed to get module id %d", __func__, ret);
1167 return ret;
1168 }
1169 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1170 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1171
1172 if(enable)
1173 param_value = effect_config.param_value;
1174
1175 /*Special handling for AEC & NS effects Param values need to be
1176 updated if module ids are same*/
1177
1178 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1179 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1180 if (ret < 0)
1181 return ret;
1182 }
1183
1184 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1185
1186 return ret;
1187}
1188
1189static void check_and_enable_effect(struct audio_device *adev)
1190{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001191 if(!voice_extn_is_dynamic_ecns_enabled())
1192 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001193
Eric Laurent637e2d42018-11-15 12:24:31 -08001194 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001195
Eric Laurent637e2d42018-11-15 12:24:31 -08001196 if (in != NULL && !in->standby) {
1197 if (in->enable_aec)
1198 enable_disable_effect(adev, EFFECT_AEC, true);
1199
1200 if (in->enable_ns &&
1201 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1202 enable_disable_effect(adev, EFFECT_NS, true);
1203 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001204 }
1205}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001206
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001207int pcm_ioctl(struct pcm *pcm, int request, ...)
1208{
1209 va_list ap;
1210 void * arg;
1211 int pcm_fd = *(int*)pcm;
1212
1213 va_start(ap, request);
1214 arg = va_arg(ap, void *);
1215 va_end(ap);
1216
1217 return ioctl(pcm_fd, request, arg);
1218}
1219
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001220int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001221 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001224 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301225 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301226 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001227 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301228 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001229
1230 if (usecase == NULL)
1231 return -EINVAL;
1232
1233 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1234
Carter Hsu2e429db2019-05-14 18:50:52 +08001235 if (usecase->type == PCM_CAPTURE) {
1236 struct stream_in *in = usecase->stream.in;
1237 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001239
1240 if (in) {
1241 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001242 list_init(&out_devices);
1243 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001244 struct listnode *node;
1245 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1246 USECASE_AUDIO_PLAYBACK_VOIP);
1247 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001248 assign_devices(&out_devices,
1249 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001250 } else if (adev->primary_output &&
1251 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001252 assign_devices(&out_devices,
1253 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001254 } else {
1255 list_for_each(node, &adev->usecase_list) {
1256 uinfo = node_to_item(node, struct audio_usecase, list);
1257 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001258 assign_devices(&out_devices,
1259 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001260 break;
1261 }
1262 }
1263 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001264
1265 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001266 in->ec_opened = true;
1267 }
1268 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001269 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1270 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1271 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001272 snd_device = usecase->in_snd_device;
1273 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001275 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001276
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001277 if (usecase->type == PCM_CAPTURE) {
1278 if (platform_get_fluence_nn_state(adev->platform) == 0) {
1279 platform_set_fluence_nn_state(adev->platform, true);
1280 ALOGD("%s: set fluence nn capture state", __func__);
1281 }
1282 }
1283
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001284#ifdef DS1_DOLBY_DAP_ENABLED
1285 audio_extn_dolby_set_dmid(adev);
1286 audio_extn_dolby_set_endpoint(adev);
1287#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001288 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001289 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301290 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001291 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001292 if (audio_extn_is_maxx_audio_enabled())
1293 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301294 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Songbaddf9f2020-11-20 13:57:39 +08001295 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1296 out = usecase->stream.out;
1297 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301298 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1299 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301300
1301 if (usecase->type == PCM_CAPTURE) {
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001302 if (platform_get_fluence_nn_state(adev->platform) == 1 &&
1303 adev->fluence_nn_usecase_id == USECASE_INVALID ) {
1304 adev->fluence_nn_usecase_id = usecase->id;
1305 ALOGD("%s: assign fluence nn usecase %d", __func__, usecase->id);
1306 }
1307 }
1308
1309 if (usecase->type == PCM_CAPTURE) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301310 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001311 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301312 ALOGD("%s: set custom mtmx params v1", __func__);
1313 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1314 }
1315 } else {
1316 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1317 }
Manish Dewangan58229382017-02-02 15:48:41 +05301318
Andy Hung756ecc12018-10-19 17:47:12 -07001319 // we shouldn't truncate mixer_path
1320 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1321 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1322 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001323 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301325 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1326 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1327 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1328 if (parms) {
1329 audio_extn_fm_set_parameters(adev, parms);
1330 str_parms_destroy(parms);
1331 }
1332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333 ALOGV("%s: exit", __func__);
1334 return 0;
1335}
1336
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001337int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001338 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001341 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301342 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001343
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301344 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001345 return -EINVAL;
1346
1347 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301348 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001349 snd_device = usecase->in_snd_device;
1350 else
1351 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001352
1353 /* disable island and power mode on supported device for voice call */
1354 if (usecase->type == VOICE_CALL) {
1355 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1356 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1357 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1358 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1359 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1360 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001361 if (voice_is_lte_call_active(adev))
1362 platform_set_tx_lpi_mode(adev->platform, false);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001363 ALOGD("%s: disable island cfg and power mode in voice tx path",
1364 __func__);
1365 }
1366 }
1367 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1368 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1369 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1370 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1371 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1372 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1373 ALOGD("%s: disable island cfg and power mode in voice rx path",
1374 __func__);
1375 }
1376 }
1377 }
1378
Andy Hung756ecc12018-10-19 17:47:12 -07001379 // we shouldn't truncate mixer_path
1380 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1381 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1382 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001383 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001384 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001385 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001386 if (usecase->type == PCM_CAPTURE) {
1387 struct stream_in *in = usecase->stream.in;
1388 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001389 struct listnode out_devices;
1390 list_init(&out_devices);
1391 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001392 in->ec_opened = false;
1393 }
1394 }
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +08001395 if (usecase->id == adev->fluence_nn_usecase_id) {
1396 platform_set_fluence_nn_state(adev->platform, false);
1397 adev->fluence_nn_usecase_id = USECASE_INVALID;
1398 ALOGD("%s: reset fluence nn capture state", __func__);
1399 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001400 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301401 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301402
1403 if (usecase->type == PCM_CAPTURE) {
1404 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001405 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301406 ALOGD("%s: reset custom mtmx params v1", __func__);
1407 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1408 }
1409 } else {
1410 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1411 }
1412
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001413 if ((usecase->type == PCM_PLAYBACK) &&
1414 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301415 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417 ALOGV("%s: exit", __func__);
1418 return 0;
1419}
1420
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001421int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301424 int i, num_devices = 0;
1425 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001426 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1427
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001428 if (snd_device < SND_DEVICE_MIN ||
1429 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001430 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001431 return -EINVAL;
1432 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001433
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001434 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001435 ALOGE("%s: Invalid sound device returned", __func__);
1436 return -EINVAL;
1437 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001438
1439 adev->snd_dev_ref_cnt[snd_device]++;
1440
1441 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1442 (platform_split_snd_device(adev->platform,
1443 snd_device,
1444 &num_devices,
1445 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001446 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001447 __func__, snd_device, device_name);
Aniket Kumar Lata990de552019-07-11 14:20:23 -07001448 /* Set backend config for A2DP to ensure slimbus configuration
1449 is correct if A2DP is already active and backend is closed
1450 and re-opened */
1451 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1452 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001453 return 0;
1454 }
1455
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001456 if (audio_extn_spkr_prot_is_enabled())
1457 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001458
Aalique Grahame22e49102018-12-18 14:23:57 -08001459 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1460
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001461 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1462 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001463 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1464 goto err;
1465 }
1466 audio_extn_dev_arbi_acquire(snd_device);
1467 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001468 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001469 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001470 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001471 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001472 } else if (platform_split_snd_device(adev->platform,
1473 snd_device,
1474 &num_devices,
1475 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301476 for (i = 0; i < num_devices; i++) {
1477 enable_snd_device(adev, new_snd_devices[i]);
1478 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001479 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001480 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001481 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301482
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001483 /* enable island and power mode on supported device */
1484 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1485 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1486 platform_set_island_cfg_on_device(adev, snd_device, true);
1487 platform_set_power_mode_on_device(adev, snd_device, true);
Kunlei Zhang91c4b332020-07-20 17:53:14 +08001488 if (voice_is_lte_call_active(adev) &&
1489 (snd_device >= SND_DEVICE_IN_BEGIN &&
1490 snd_device < SND_DEVICE_IN_END))
1491 platform_set_tx_lpi_mode(adev->platform, true);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001492 ALOGD("%s: enable island cfg and power mode on: %s",
1493 __func__, device_name);
1494 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301495
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301496 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1497 if (audio_extn_a2dp_start_playback() < 0) {
1498 ALOGE(" fail to configure A2dp Source control path ");
1499 goto err;
1500 } else {
1501 adev->a2dp_started = true;
1502 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001503 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001504
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001505 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1506 (audio_extn_a2dp_start_capture() < 0)) {
1507 ALOGE(" fail to configure A2dp Sink control path ");
1508 goto err;
1509 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301510
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001511 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1512 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1513 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1514 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1515 ALOGE(" fail to configure sco control path ");
1516 goto err;
1517 }
Zhou Song12c29502019-03-16 10:37:18 +08001518 }
1519
Zhou Song331c8e52019-08-26 14:16:12 +08001520 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001521 /* due to the possibility of calibration overwrite between listen
1522 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001523 audio_extn_sound_trigger_update_device_status(snd_device,
1524 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301525 audio_extn_listen_update_device_status(snd_device,
1526 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001527 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001528 audio_extn_sound_trigger_update_device_status(snd_device,
1529 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301530 audio_extn_listen_update_device_status(snd_device,
1531 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001533 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001534 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001535 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301536
1537 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1538 !adev->native_playback_enabled &&
1539 audio_is_true_native_stream_active(adev)) {
1540 ALOGD("%s: %d: napb: enabling native mode in hardware",
1541 __func__, __LINE__);
1542 audio_route_apply_and_update_path(adev->audio_route,
1543 "true-native-mode");
1544 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301545 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301546 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1547 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001548 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001549 ALOGD("%s: init ec ref loopback", __func__);
1550 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1551 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001554err:
1555 adev->snd_dev_ref_cnt[snd_device]--;
1556 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557}
1558
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001559int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001560 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301562 int i, num_devices = 0;
1563 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001564 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001566 if (snd_device < SND_DEVICE_MIN ||
1567 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001568 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001569 return -EINVAL;
1570 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001571
1572 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1573 ALOGE("%s: Invalid sound device returned", __func__);
1574 return -EINVAL;
1575 }
1576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1578 ALOGE("%s: device ref cnt is already 0", __func__);
1579 return -EINVAL;
1580 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001583
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001586 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301587
Aalique Grahame22e49102018-12-18 14:23:57 -08001588 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1589
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001590 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1591 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001592 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001593
1594 // when speaker device is disabled, reset swap.
1595 // will be renabled on usecase start
1596 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001597 } else if (platform_split_snd_device(adev->platform,
1598 snd_device,
1599 &num_devices,
1600 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301601 for (i = 0; i < num_devices; i++) {
1602 disable_snd_device(adev, new_snd_devices[i]);
1603 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001604 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001605 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001606 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001607 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001608
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301609 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301610 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301611 adev->a2dp_started = false;
1612 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001613 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001614 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001615 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301616 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001617 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301618 adev->native_playback_enabled) {
1619 ALOGD("%s: %d: napb: disabling native mode in hardware",
1620 __func__, __LINE__);
1621 audio_route_reset_and_update_path(adev->audio_route,
1622 "true-native-mode");
1623 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001624 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301625 adev->asrc_mode_enabled) {
1626 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301627 disable_asrc_mode(adev);
1628 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001629 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301630 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001631 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001632 ALOGD("%s: deinit ec ref loopback", __func__);
1633 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1634 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001635
1636 audio_extn_utils_release_snd_device(snd_device);
1637 } else {
1638 if (platform_split_snd_device(adev->platform,
1639 snd_device,
1640 &num_devices,
1641 new_snd_devices) == 0) {
1642 for (i = 0; i < num_devices; i++) {
1643 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1644 }
1645 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 return 0;
1649}
1650
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001651/*
1652 legend:
1653 uc - existing usecase
1654 new_uc - new usecase
1655 d1, d11, d2 - SND_DEVICE enums
1656 a1, a2 - corresponding ANDROID device enums
1657 B1, B2 - backend strings
1658
1659case 1
1660 uc->dev d1 (a1) B1
1661 new_uc->dev d1 (a1), d2 (a2) B1, B2
1662
1663 resolution: disable and enable uc->dev on d1
1664
1665case 2
1666 uc->dev d1 (a1) B1
1667 new_uc->dev d11 (a1) B1
1668
1669 resolution: need to switch uc since d1 and d11 are related
1670 (e.g. speaker and voice-speaker)
1671 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1672
1673case 3
1674 uc->dev d1 (a1) B1
1675 new_uc->dev d2 (a2) B2
1676
1677 resolution: no need to switch uc
1678
1679case 4
1680 uc->dev d1 (a1) B1
1681 new_uc->dev d2 (a2) B1
1682
1683 resolution: disable enable uc-dev on d2 since backends match
1684 we cannot enable two streams on two different devices if they
1685 share the same backend. e.g. if offload is on speaker device using
1686 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1687 using the same backend, offload must also be switched to voice-handset.
1688
1689case 5
1690 uc->dev d1 (a1) B1
1691 new_uc->dev d1 (a1), 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.
1696
1697case 6
1698 uc->dev d1 (a1) B1
1699 new_uc->dev d2 (a1) B2
1700
1701 resolution: no need to switch
1702
1703case 7
1704 uc->dev d1 (a1), d2 (a2) B1, B2
1705 new_uc->dev d1 (a1) B1
1706
1707 resolution: no need to switch
1708
Zhou Song4ba65882018-07-09 14:48:07 +08001709case 8
1710 uc->dev d1 (a1) B1
1711 new_uc->dev d11 (a1), d2 (a2) B1, B2
1712 resolution: compared to case 1, for this case, d1 and d11 are related
1713 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301714
1715case 9
1716 uc->dev d1 (a1), d2(a2) B1 B2
1717 new_uc->dev d1 (a1), d22 (a2) B1, B2
1718 resolution: disable enable uc-dev on d2 since backends match
1719 we cannot enable two streams on two different devices if they
1720 share the same backend. This is special case for combo use case
1721 with a2dp and sco devices which uses same backend.
1722 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001723*/
1724static snd_device_t derive_playback_snd_device(void * platform,
1725 struct audio_usecase *uc,
1726 struct audio_usecase *new_uc,
1727 snd_device_t new_snd_device)
1728{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001729 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001730
1731 snd_device_t d1 = uc->out_snd_device;
1732 snd_device_t d2 = new_snd_device;
1733
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001734 list_init(&a1);
1735 list_init(&a2);
1736
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301737 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301738 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001739 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1740 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301741 break;
1742 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001743 assign_devices(&a1, &uc->stream.out->device_list);
1744 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301745 break;
1746 }
1747
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001748 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001749 if (!compare_devices(&a1, &a2) &&
1750 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001751 snd_device_t d3[2];
1752 int num_devices = 0;
1753 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001754 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001755 &num_devices,
1756 d3);
1757 if (ret < 0) {
1758 if (ret != -ENOSYS) {
1759 ALOGW("%s failed to split snd_device %d",
1760 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001761 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001762 }
1763 goto end;
1764 }
1765
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001766 if (platform_check_backends_match(d3[0], d3[1])) {
1767 return d2; // case 5
1768 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301769 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1770 platform_check_backends_match(d1, d2))
1771 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001772 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301773 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001774 // check if d1 is related to any of d3's
1775 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001776 return d1; // case 1
1777 else
1778 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001779 }
1780 } else {
1781 if (platform_check_backends_match(d1, d2)) {
1782 return d2; // case 2, 4
1783 } else {
1784 return d1; // case 6, 3
1785 }
1786 }
1787
1788end:
1789 return d2; // return whatever was calculated before.
1790}
1791
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001792static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301793 struct audio_usecase *uc_info,
1794 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795{
1796 struct listnode *node;
1797 struct audio_usecase *usecase;
1798 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301799 snd_device_t uc_derive_snd_device;
1800 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001801 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1802 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001803 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301804 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001805 /*
1806 * This function is to make sure that all the usecases that are active on
1807 * the hardware codec backend are always routed to any one device that is
1808 * handled by the hardware codec.
1809 * For example, if low-latency and deep-buffer usecases are currently active
1810 * on speaker and out_set_parameters(headset) is received on low-latency
1811 * output, then we have to make sure deep-buffer is also switched to headset,
1812 * because of the limitation that both the devices cannot be enabled
1813 * at the same time as they share the same backend.
1814 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001815 /*
1816 * This call is to check if we need to force routing for a particular stream
1817 * If there is a backend configuration change for the device when a
1818 * new stream starts, then ADM needs to be closed and re-opened with the new
1819 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001820 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001821 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001822 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1823 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301824 /* For a2dp device reconfigure all active sessions
1825 * with new AFE encoder format based on a2dp state
1826 */
1827 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301828 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1829 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301830 audio_extn_a2dp_is_force_device_switch()) {
1831 force_routing = true;
1832 force_restart_session = true;
1833 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001834
1835 /*
1836 * Island cfg and power mode config needs to set before AFE port start.
1837 * Set force routing in case of voice device was enable before.
1838 */
1839 if (uc_info->type == VOICE_CALL &&
1840 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001841 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001842 platform_check_and_update_island_power_status(adev->platform,
1843 uc_info,
1844 snd_device)) {
1845 force_routing = true;
1846 ALOGD("%s:becf: force routing %d for power mode supported device",
1847 __func__, force_routing);
1848 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301849 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1850
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001852 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001853 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001854 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1855 switch_device[i] = false;
1856
1857 list_for_each(node, &adev->usecase_list) {
1858 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001859
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301860 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1861 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301862 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301863 platform_get_snd_device_name(usecase->out_snd_device),
1864 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301865 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1866 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301867 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1868 usecase, uc_info, snd_device);
1869 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001870 (is_codec_backend_out_device_type(&usecase->device_list) ||
1871 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1872 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1873 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1874 is_a2dp_out_device_type(&usecase->device_list) ||
1875 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301876 ((force_restart_session) ||
1877 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301878 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1879 __func__, use_case_table[usecase->id],
1880 platform_get_snd_device_name(usecase->out_snd_device));
1881 disable_audio_route(adev, usecase);
1882 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301883 /* Enable existing usecase on derived playback device */
1884 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301885 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 }
1888 }
1889
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301890 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1891 num_uc_to_switch);
1892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001893 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001894 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301896 /* Make sure the previous devices to be disabled first and then enable the
1897 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 list_for_each(node, &adev->usecase_list) {
1899 usecase = node_to_item(node, struct audio_usecase, list);
1900 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001901 /* Check if output sound device to be switched can be split and if any
1902 of the split devices match with derived sound device */
1903 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1904 &num_devices, split_snd_devices) == 0) {
1905 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1906 for (i = 0; i < num_devices; i++) {
1907 /* Disable devices that do not match with derived sound device */
1908 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1909 disable_snd_device(adev, split_snd_devices[i]);
1910 }
1911 } else {
1912 disable_snd_device(adev, usecase->out_snd_device);
1913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001914 }
1915 }
1916
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001917 list_for_each(node, &adev->usecase_list) {
1918 usecase = node_to_item(node, struct audio_usecase, list);
1919 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001920 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1921 &num_devices, split_snd_devices) == 0) {
1922 /* Enable derived sound device only if it does not match with
1923 one of the split sound devices. This is because the matching
1924 sound device was not disabled */
1925 bool should_enable = true;
1926 for (i = 0; i < num_devices; i++) {
1927 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1928 should_enable = false;
1929 break;
1930 }
1931 }
1932 if (should_enable)
1933 enable_snd_device(adev, derive_snd_device[usecase->id]);
1934 } else {
1935 enable_snd_device(adev, derive_snd_device[usecase->id]);
1936 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001937 }
1938 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 /* Re-route all the usecases on the shared backend other than the
1941 specified usecase to new snd devices */
1942 list_for_each(node, &adev->usecase_list) {
1943 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301944 /* Update the out_snd_device only before enabling the audio route */
1945 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301946 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05301947 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1948 use_case_table[usecase->id],
1949 platform_get_snd_device_name(usecase->out_snd_device));
1950 /* Update voc calibration before enabling Voice/VoIP route */
1951 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1952 status = platform_switch_voice_call_device_post(adev->platform,
1953 usecase->out_snd_device,
1954 platform_get_input_snd_device(
1955 adev->platform, NULL,
1956 &uc_info->device_list,
1957 usecase->type));
1958 enable_audio_route(adev, usecase);
1959 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1960 out_set_voip_volume(&usecase->stream.out->stream,
1961 usecase->stream.out->volume_l,
1962 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301963 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 }
1965 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 }
1967}
1968
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301969static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001970 struct audio_usecase *uc_info,
1971 snd_device_t snd_device)
1972{
1973 struct listnode *node;
1974 struct audio_usecase *usecase;
1975 bool switch_device[AUDIO_USECASE_MAX];
1976 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001977 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001978 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001979
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301980 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1981 snd_device);
1982 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301983
1984 /*
1985 * Make sure out devices is checked against out codec backend device and
1986 * also in devices against in codec backend. Checking out device against in
1987 * codec backend or vice versa causes issues.
1988 */
1989 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001990 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001991
1992 /*
1993 * Island cfg and power mode config needs to set before AFE port start.
1994 * Set force routing in case of voice device was enable before.
1995 */
1996
1997 if (uc_info->type == VOICE_CALL &&
1998 voice_extn_is_voice_power_mode_supported() &&
Kunlei Zhang67cc7072020-12-18 17:16:49 +08001999 is_supported_conc_usecase_for_power_mode_call(adev) &&
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08002000 platform_check_and_update_island_power_status(adev->platform,
2001 uc_info,
2002 snd_device)) {
2003 force_routing = true;
2004 ALOGD("%s:becf: force routing %d for power mode supported device",
2005 __func__, force_routing);
2006 }
2007
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002008 /*
2009 * This function is to make sure that all the active capture usecases
2010 * are always routed to the same input sound device.
2011 * For example, if audio-record and voice-call usecases are currently
2012 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
2013 * is received for voice call then we have to make sure that audio-record
2014 * usecase is also switched to earpiece i.e. voice-dmic-ef,
2015 * because of the limitation that two devices cannot be enabled
2016 * at the same time if they share the same backend.
2017 */
2018 for (i = 0; i < AUDIO_USECASE_MAX; i++)
2019 switch_device[i] = false;
2020
2021 list_for_each(node, &adev->usecase_list) {
2022 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05302023 /*
2024 * TODO: Enhance below condition to handle BT sco/USB multi recording
2025 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302026
2027 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
2028 (usecase->in_snd_device != snd_device || force_routing));
2029 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
2030 platform_is_call_proxy_snd_device(usecase->in_snd_device);
2031 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002032 ((backend_check_cond &&
2033 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08002034 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002035 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002036 is_single_device_type_equal(&usecase->device_list,
2037 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08002038 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002039 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07002040 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05302041 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002042 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07002043 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002044 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002045 switch_device[usecase->id] = true;
2046 num_uc_to_switch++;
2047 }
2048 }
2049
2050 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07002051 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002052
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05302053 /* Make sure the previous devices to be disabled first and then enable the
2054 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002055 list_for_each(node, &adev->usecase_list) {
2056 usecase = node_to_item(node, struct audio_usecase, list);
2057 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002058 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08002059 }
2060 }
2061
2062 list_for_each(node, &adev->usecase_list) {
2063 usecase = node_to_item(node, struct audio_usecase, list);
2064 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002065 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002066 }
2067 }
2068
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002069 /* Re-route all the usecases on the shared backend other than the
2070 specified usecase to new snd devices */
2071 list_for_each(node, &adev->usecase_list) {
2072 usecase = node_to_item(node, struct audio_usecase, list);
2073 /* Update the in_snd_device only before enabling the audio route */
2074 if (switch_device[usecase->id] ) {
2075 usecase->in_snd_device = snd_device;
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302076 /* Update voc calibration before enabling Voice/VoIP route */
2077 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2078 snd_device_t voip_snd_device;
2079 voip_snd_device = platform_get_output_snd_device(adev->platform,
2080 usecase->stream.out,
2081 usecase->type);
2082 status = platform_switch_voice_call_device_post(adev->platform,
2083 voip_snd_device,
2084 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002085 }
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05302086 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002087 }
2088 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002089 }
2090}
2091
Mingming Yin3a941d42016-02-17 18:08:05 -08002092static void reset_hdmi_sink_caps(struct stream_out *out) {
2093 int i = 0;
2094
2095 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2096 out->supported_channel_masks[i] = 0;
2097 }
2098 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2099 out->supported_formats[i] = 0;
2100 }
2101 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2102 out->supported_sample_rates[i] = 0;
2103 }
2104}
2105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002107static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108{
Mingming Yin3a941d42016-02-17 18:08:05 -08002109 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002110 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2111 out->extconn.cs.controller,
2112 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113
Mingming Yin3a941d42016-02-17 18:08:05 -08002114 reset_hdmi_sink_caps(out);
2115
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002116 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002117 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002118 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002119 out->extconn.cs.stream);
2120 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002121 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002122 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002123 }
2124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002127 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002128 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002129 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2130 case 6:
2131 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2132 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2133 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2134 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2135 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2136 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 break;
2138 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002139 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002140 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 break;
2142 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002143
2144 // check channel format caps
2145 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002146 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2147 out->extconn.cs.controller,
2148 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002149 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2150 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2151 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2152 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2153 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2154 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2155 }
2156
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002157 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2158 out->extconn.cs.controller,
2159 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002160 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2161 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2162 }
2163
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002164 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2165 out->extconn.cs.controller,
2166 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002167 ALOGV(":%s HDMI supports DTS format", __func__);
2168 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2169 }
2170
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002171 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2172 out->extconn.cs.controller,
2173 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002174 ALOGV(":%s HDMI supports DTS HD format", __func__);
2175 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2176 }
2177
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002178 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2179 out->extconn.cs.controller,
2180 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002181 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2182 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2183 }
2184
Mingming Yin3a941d42016-02-17 18:08:05 -08002185
2186 // check sample rate caps
2187 i = 0;
2188 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002189 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2190 out->extconn.cs.controller,
2191 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002192 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2193 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2194 }
2195 }
2196
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002197 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198}
2199
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002200static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2201 uint32_t *supported_sample_rates __unused,
2202 uint32_t max_rates __unused)
2203{
2204 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2205 supported_sample_rates,
2206 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302207 ssize_t i = 0;
2208
2209 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002210 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2211 supported_sample_rates[i]);
2212 }
2213 return count;
2214}
2215
2216static inline int read_usb_sup_channel_masks(bool is_playback,
2217 audio_channel_mask_t *supported_channel_masks,
2218 uint32_t max_masks)
2219{
2220 int channels = audio_extn_usb_get_max_channels(is_playback);
2221 int channel_count;
2222 uint32_t num_masks = 0;
2223 if (channels > MAX_HIFI_CHANNEL_COUNT)
2224 channels = MAX_HIFI_CHANNEL_COUNT;
2225
2226 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002227 // start from 2 channels as framework currently doesn't support mono.
2228 if (channels >= FCC_2) {
2229 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2230 }
2231 for (channel_count = FCC_2;
2232 channel_count <= channels && num_masks < max_masks;
2233 ++channel_count) {
2234 supported_channel_masks[num_masks++] =
2235 audio_channel_mask_for_index_assignment_from_count(channel_count);
2236 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002237 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002238 // For capture we report all supported channel masks from 1 channel up.
2239 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002240 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2241 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002242 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2243 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2244 if (channel_count <= FCC_2) {
2245 mask = audio_channel_in_mask_from_count(channel_count);
2246 supported_channel_masks[num_masks++] = mask;
2247 }
2248 const audio_channel_mask_t index_mask =
2249 audio_channel_mask_for_index_assignment_from_count(channel_count);
2250 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2251 supported_channel_masks[num_masks++] = index_mask;
2252 }
2253 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002254 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302255
vincenttewf51c94e2019-05-07 10:28:53 +08002256 for (size_t i = 0; i < num_masks; ++i) {
2257 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2258 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302259 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002260 return num_masks;
2261}
2262
2263static inline int read_usb_sup_formats(bool is_playback __unused,
2264 audio_format_t *supported_formats,
2265 uint32_t max_formats __unused)
2266{
2267 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2268 switch (bitwidth) {
2269 case 24:
2270 // XXX : usb.c returns 24 for s24 and s24_le?
2271 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2272 break;
2273 case 32:
2274 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2275 break;
2276 case 16:
2277 default :
2278 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2279 break;
2280 }
2281 ALOGV("%s: %s supported format %d", __func__,
2282 is_playback ? "P" : "C", bitwidth);
2283 return 1;
2284}
2285
2286static inline int read_usb_sup_params_and_compare(bool is_playback,
2287 audio_format_t *format,
2288 audio_format_t *supported_formats,
2289 uint32_t max_formats,
2290 audio_channel_mask_t *mask,
2291 audio_channel_mask_t *supported_channel_masks,
2292 uint32_t max_masks,
2293 uint32_t *rate,
2294 uint32_t *supported_sample_rates,
2295 uint32_t max_rates) {
2296 int ret = 0;
2297 int num_formats;
2298 int num_masks;
2299 int num_rates;
2300 int i;
2301
2302 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2303 max_formats);
2304 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2305 max_masks);
2306
2307 num_rates = read_usb_sup_sample_rates(is_playback,
2308 supported_sample_rates, max_rates);
2309
2310#define LUT(table, len, what, dflt) \
2311 for (i=0; i<len && (table[i] != what); i++); \
2312 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2313
2314 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2315 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2316 LUT(supported_sample_rates, num_rates, *rate, 0);
2317
2318#undef LUT
2319 return ret < 0 ? -EINVAL : 0; // HACK TBD
2320}
2321
Alexy Josephb1379942016-01-29 15:49:38 -08002322audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002323 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002324{
2325 struct audio_usecase *usecase;
2326 struct listnode *node;
2327
2328 list_for_each(node, &adev->usecase_list) {
2329 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002330 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002331 ALOGV("%s: usecase id %d", __func__, usecase->id);
2332 return usecase->id;
2333 }
2334 }
2335 return USECASE_INVALID;
2336}
2337
Alexy Josephb1379942016-01-29 15:49:38 -08002338struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002339 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002340{
2341 struct audio_usecase *usecase;
2342 struct listnode *node;
2343
2344 list_for_each(node, &adev->usecase_list) {
2345 usecase = node_to_item(node, struct audio_usecase, list);
2346 if (usecase->id == uc_id)
2347 return usecase;
2348 }
2349 return NULL;
2350}
2351
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302352/*
2353 * is a true native playback active
2354 */
2355bool audio_is_true_native_stream_active(struct audio_device *adev)
2356{
2357 bool active = false;
2358 int i = 0;
2359 struct listnode *node;
2360
2361 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2362 ALOGV("%s:napb: not in true mode or non hdphones device",
2363 __func__);
2364 active = false;
2365 goto exit;
2366 }
2367
2368 list_for_each(node, &adev->usecase_list) {
2369 struct audio_usecase *uc;
2370 uc = node_to_item(node, struct audio_usecase, list);
2371 struct stream_out *curr_out =
2372 (struct stream_out*) uc->stream.out;
2373
2374 if (curr_out && PCM_PLAYBACK == uc->type) {
2375 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2376 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2377 uc->id, curr_out->sample_rate,
2378 curr_out->bit_width,
2379 platform_get_snd_device_name(uc->out_snd_device));
2380
2381 if (is_offload_usecase(uc->id) &&
2382 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2383 active = true;
2384 ALOGD("%s:napb:native stream detected", __func__);
2385 }
2386 }
2387 }
2388exit:
2389 return active;
2390}
2391
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002392uint32_t adev_get_dsp_bit_width_enforce_mode()
2393{
2394 if (adev == NULL) {
2395 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2396 return 0;
2397 }
2398 return adev->dsp_bit_width_enforce_mode;
2399}
2400
2401static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2402{
2403 char value[PROPERTY_VALUE_MAX];
2404 int trial;
2405 uint32_t dsp_bit_width_enforce_mode = 0;
2406
2407 if (!mixer) {
2408 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2409 __func__);
2410 return 0;
2411 }
2412
2413 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2414 value, NULL) > 0) {
2415 trial = atoi(value);
2416 switch (trial) {
2417 case 16:
2418 dsp_bit_width_enforce_mode = 16;
2419 break;
2420 case 24:
2421 dsp_bit_width_enforce_mode = 24;
2422 break;
2423 case 32:
2424 dsp_bit_width_enforce_mode = 32;
2425 break;
2426 default:
2427 dsp_bit_width_enforce_mode = 0;
2428 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2429 break;
2430 }
2431 }
2432
2433 return dsp_bit_width_enforce_mode;
2434}
2435
2436static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2437 uint32_t enforce_mode,
2438 bool enable)
2439{
2440 struct mixer_ctl *ctl = NULL;
2441 const char *mixer_ctl_name = "ASM Bit Width";
2442 uint32_t asm_bit_width_mode = 0;
2443
2444 if (enforce_mode == 0) {
2445 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2446 return;
2447 }
2448
2449 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2450 if (!ctl) {
2451 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2452 __func__, mixer_ctl_name);
2453 return;
2454 }
2455
2456 if (enable)
2457 asm_bit_width_mode = enforce_mode;
2458 else
2459 asm_bit_width_mode = 0;
2460
2461 ALOGV("%s DSP bit width feature status is %d width=%d",
2462 __func__, enable, asm_bit_width_mode);
2463 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2464 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2465 asm_bit_width_mode);
2466
2467 return;
2468}
2469
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302470/*
2471 * if native DSD playback active
2472 */
2473bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2474{
2475 bool active = false;
2476 struct listnode *node = NULL;
2477 struct audio_usecase *uc = NULL;
2478 struct stream_out *curr_out = NULL;
2479
2480 list_for_each(node, &adev->usecase_list) {
2481 uc = node_to_item(node, struct audio_usecase, list);
2482 curr_out = (struct stream_out*) uc->stream.out;
2483
2484 if (curr_out && PCM_PLAYBACK == uc->type &&
2485 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2486 active = true;
2487 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302488 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302489 }
2490 }
2491 return active;
2492}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302493
2494static bool force_device_switch(struct audio_usecase *usecase)
2495{
2496 bool ret = false;
2497 bool is_it_true_mode = false;
2498
Zhou Song30f2c3e2018-02-08 14:02:15 +08002499 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302500 usecase->type == TRANSCODE_LOOPBACK_RX ||
2501 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002502 return false;
2503 }
2504
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002505 if(usecase->stream.out == NULL) {
2506 ALOGE("%s: stream.out is NULL", __func__);
2507 return false;
2508 }
2509
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302510 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002511 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002512 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2513 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302514 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2515 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2516 (!is_it_true_mode && adev->native_playback_enabled)){
2517 ret = true;
2518 ALOGD("napb: time to toggle native mode");
2519 }
2520 }
2521
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302522 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302523 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2524 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002525 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302526 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302527 ALOGD("Force a2dp device switch to update new encoder config");
2528 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002529 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302530
Florian Pfister1a84f312018-07-19 14:38:18 +02002531 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302532 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2533 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002534 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302535 return ret;
2536}
2537
Aalique Grahame22e49102018-12-18 14:23:57 -08002538static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2539{
2540 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2541}
2542
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302543bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2544{
2545 bool ret=false;
2546 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002547 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2548 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302549 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2550 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002551 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302552 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002553 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2554 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302555 ret = true;
2556
2557 return ret;
2558}
2559
2560bool is_a2dp_device(snd_device_t out_snd_device)
2561{
2562 bool ret=false;
2563 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2564 ret = true;
2565
2566 return ret;
2567}
2568
2569bool is_bt_soc_on(struct audio_device *adev)
2570{
2571 struct mixer_ctl *ctl;
2572 char *mixer_ctl_name = "BT SOC status";
2573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2574 bool bt_soc_status = true;
2575 if (!ctl) {
2576 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2577 __func__, mixer_ctl_name);
2578 /*This is to ensure we dont break targets which dont have the kernel change*/
2579 return true;
2580 }
2581 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2582 ALOGD("BT SOC status: %d",bt_soc_status);
2583 return bt_soc_status;
2584}
2585
Zhou Song331c8e52019-08-26 14:16:12 +08002586static int configure_btsco_sample_rate(snd_device_t snd_device)
2587{
2588 struct mixer_ctl *ctl = NULL;
2589 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2590 char *rate_str = NULL;
2591 bool is_rx_dev = true;
2592
2593 if (is_btsco_device(snd_device, snd_device)) {
2594 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2595 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2596 if (!ctl_sr_tx || !ctl_sr_rx) {
2597 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2598 if (!ctl_sr)
2599 return -ENOSYS;
2600 }
2601
2602 switch (snd_device) {
2603 case SND_DEVICE_OUT_BT_SCO:
2604 rate_str = "KHZ_8";
2605 break;
2606 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2607 case SND_DEVICE_IN_BT_SCO_MIC:
2608 rate_str = "KHZ_8";
2609 is_rx_dev = false;
2610 break;
2611 case SND_DEVICE_OUT_BT_SCO_WB:
2612 rate_str = "KHZ_16";
2613 break;
2614 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2615 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2616 rate_str = "KHZ_16";
2617 is_rx_dev = false;
2618 break;
2619 default:
2620 return 0;
2621 }
2622
2623 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2624 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2625 return -ENOSYS;
2626 }
2627 return 0;
2628}
2629
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302630int out_standby_l(struct audio_stream *stream);
2631
Eric Laurent637e2d42018-11-15 12:24:31 -08002632struct stream_in *adev_get_active_input(const struct audio_device *adev)
2633{
2634 struct listnode *node;
2635 struct stream_in *last_active_in = NULL;
2636
2637 /* Get last added active input.
2638 * TODO: We may use a priority mechanism to pick highest priority active source */
2639 list_for_each(node, &adev->usecase_list)
2640 {
2641 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2642 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2643 last_active_in = usecase->stream.in;
2644 }
2645
2646 return last_active_in;
2647}
2648
2649struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2650{
2651 struct listnode *node;
2652
2653 /* First check active inputs with voice communication source and then
2654 * any input if audio mode is in communication */
2655 list_for_each(node, &adev->usecase_list)
2656 {
2657 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2658 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2659 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2660 return usecase->stream.in;
2661 }
2662 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2663 return adev_get_active_input(adev);
2664
2665 return NULL;
2666}
2667
Carter Hsu2e429db2019-05-14 18:50:52 +08002668/*
2669 * Aligned with policy.h
2670 */
2671static inline int source_priority(int inputSource)
2672{
2673 switch (inputSource) {
2674 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2675 return 9;
2676 case AUDIO_SOURCE_CAMCORDER:
2677 return 8;
2678 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2679 return 7;
2680 case AUDIO_SOURCE_UNPROCESSED:
2681 return 6;
2682 case AUDIO_SOURCE_MIC:
2683 return 5;
2684 case AUDIO_SOURCE_ECHO_REFERENCE:
2685 return 4;
2686 case AUDIO_SOURCE_FM_TUNER:
2687 return 3;
2688 case AUDIO_SOURCE_VOICE_RECOGNITION:
2689 return 2;
2690 case AUDIO_SOURCE_HOTWORD:
2691 return 1;
2692 default:
2693 break;
2694 }
2695 return 0;
2696}
2697
2698static struct stream_in *get_priority_input(struct audio_device *adev)
2699{
2700 struct listnode *node;
2701 struct audio_usecase *usecase;
2702 int last_priority = 0, priority;
2703 struct stream_in *priority_in = NULL;
2704 struct stream_in *in;
2705
2706 list_for_each(node, &adev->usecase_list) {
2707 usecase = node_to_item(node, struct audio_usecase, list);
2708 if (usecase->type == PCM_CAPTURE) {
2709 in = usecase->stream.in;
2710 if (!in)
2711 continue;
2712 priority = source_priority(in->source);
2713
2714 if (priority > last_priority) {
2715 last_priority = priority;
2716 priority_in = in;
2717 }
2718 }
2719 }
2720 return priority_in;
2721}
2722
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002723int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002725 snd_device_t out_snd_device = SND_DEVICE_NONE;
2726 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 struct audio_usecase *usecase = NULL;
2728 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002729 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002730 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302731 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002732 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302735 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2736
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 usecase = get_usecase_from_list(adev, uc_id);
2738 if (usecase == NULL) {
2739 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2740 return -EINVAL;
2741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002743 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002744 (usecase->type == VOIP_CALL) ||
Derek Chena30a5f42019-12-03 11:17:09 -05002745 (usecase->type == PCM_HFP_CALL)||
Fei Tongaffdf732020-02-20 20:39:05 +08002746 (usecase->type == ICC_CALL) ||
2747 (usecase->type == SYNTH_LOOPBACK)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302748 if(usecase->stream.out == NULL) {
2749 ALOGE("%s: stream.out is NULL", __func__);
2750 return -EINVAL;
2751 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002752 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002753 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2754 uc_id);
2755 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2756 uc_id);
2757 } else {
2758 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302759 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002760 in_snd_device = platform_get_input_snd_device(adev->platform,
2761 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302762 &usecase->stream.out->device_list,
2763 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002764 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002765 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302766 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302767 if (usecase->stream.inout == NULL) {
2768 ALOGE("%s: stream.inout is NULL", __func__);
2769 return -EINVAL;
2770 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002771 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302772 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2773 stream_out.format = usecase->stream.inout->out_config.format;
2774 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302775 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002776 assign_devices(&usecase->device_list,
2777 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302778 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2779 if (usecase->stream.inout == NULL) {
2780 ALOGE("%s: stream.inout is NULL", __func__);
2781 return -EINVAL;
2782 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302783 struct listnode out_devices;
2784 list_init(&out_devices);
2785 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2786 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002787 assign_devices(&usecase->device_list,
2788 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002789 } else {
2790 /*
2791 * If the voice call is active, use the sound devices of voice call usecase
2792 * so that it would not result any device switch. All the usecases will
2793 * be switched to new device when select_devices() is called for voice call
2794 * usecase. This is to avoid switching devices for voice call when
2795 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002796 * choose voice call device only if the use case device is
2797 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002798 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002799 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002800 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002801 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002802 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2803 is_codec_backend_out_device_type(&usecase->device_list)) ||
2804 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2805 is_codec_backend_in_device_type(&usecase->device_list)) ||
2806 is_single_device_type_equal(&vc_usecase->device_list,
2807 AUDIO_DEVICE_OUT_HEARING_AID) ||
2808 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002809 AUDIO_DEVICE_IN_VOICE_CALL) ||
2810 (is_single_device_type_equal(&usecase->device_list,
2811 AUDIO_DEVICE_IN_USB_HEADSET) &&
2812 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasiri5edba852021-01-28 14:52:38 +05302813 AUDIO_DEVICE_OUT_USB_HEADSET))||
2814 (is_single_device_type_equal(&usecase->device_list,
2815 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2816 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002817 in_snd_device = vc_usecase->in_snd_device;
2818 out_snd_device = vc_usecase->out_snd_device;
2819 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002820 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002821 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002822 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002823 if ((voip_usecase != NULL) &&
2824 (usecase->type == PCM_PLAYBACK) &&
2825 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002826 out_snd_device_backend_match = platform_check_backends_match(
2827 voip_usecase->out_snd_device,
2828 platform_get_output_snd_device(
2829 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302830 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002831 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002832 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2833 (is_codec_backend_out_device_type(&usecase->device_list) ||
2834 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002835 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002836 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002837 in_snd_device = voip_usecase->in_snd_device;
2838 out_snd_device = voip_usecase->out_snd_device;
2839 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002840 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002841 hfp_ucid = audio_extn_hfp_get_usecase();
2842 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002843 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002844 in_snd_device = hfp_usecase->in_snd_device;
2845 out_snd_device = hfp_usecase->out_snd_device;
2846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002847 }
2848 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302849 if (usecase->stream.out == NULL) {
2850 ALOGE("%s: stream.out is NULL", __func__);
2851 return -EINVAL;
2852 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002853 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002854 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002855 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002856 struct stream_out *voip_out = adev->primary_output;
2857 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002858 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002859 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2860 else
2861 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302862 usecase->stream.out,
2863 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002864 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002865
Eric Laurent637e2d42018-11-15 12:24:31 -08002866 if (voip_usecase)
2867 voip_out = voip_usecase->stream.out;
2868
2869 if (usecase->stream.out == voip_out && voip_in != NULL)
2870 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002872 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302873 if (usecase->stream.in == NULL) {
2874 ALOGE("%s: stream.in is NULL", __func__);
2875 return -EINVAL;
2876 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002877 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002878 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002879 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002880 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002881 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002882 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002883
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002884 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002885 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002886 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2887 USECASE_AUDIO_PLAYBACK_VOIP);
2888
Carter Hsu2e429db2019-05-14 18:50:52 +08002889 usecase->stream.in->enable_ec_port = false;
2890
Zhou Song62ea0282020-03-22 19:53:01 +08002891 bool is_ha_usecase = adev->ha_proxy_enable ?
2892 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2893 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2894 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002895 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002896 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002897 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002898 } else if (adev->primary_output &&
2899 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002900 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002901 } else {
2902 /* forcing speaker o/p device to get matching i/p pair
2903 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002904 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002905 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002906 priority_in = voip_in;
2907 } else {
2908 /* get the input with the highest priority source*/
2909 priority_in = get_priority_input(adev);
2910
Susan Wang727dd6b2021-03-26 11:28:59 -04002911 if (!priority_in ||
2912 audio_extn_auto_hal_overwrite_priority_for_auto(usecase->stream.in))
Carter Hsu2e429db2019-05-14 18:50:52 +08002913 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002914 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04002915 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_IN_BUS)){
2916 in_snd_device = audio_extn_auto_hal_get_snd_device_for_car_audio_stream(priority_in->car_audio_stream);
2917 }
2918 else
2919 in_snd_device = platform_get_input_snd_device(adev->platform,
2920 priority_in,
2921 &out_devices,
2922 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002924 }
2925 }
2926
2927 if (out_snd_device == usecase->out_snd_device &&
2928 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302929
2930 if (!force_device_switch(usecase))
2931 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 }
2933
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002934 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002935 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002936 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002937 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2938 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302939 }
2940
Aalique Grahame22e49102018-12-18 14:23:57 -08002941 if (out_snd_device != SND_DEVICE_NONE &&
2942 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2943 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2944 __func__,
2945 use_case_table[uc_id],
2946 adev->last_logged_snd_device[uc_id][0],
2947 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2948 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2949 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2950 -1,
2951 out_snd_device,
2952 platform_get_snd_device_name(out_snd_device),
2953 platform_get_snd_device_acdb_id(out_snd_device));
2954 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2955 }
2956 if (in_snd_device != SND_DEVICE_NONE &&
2957 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2958 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2959 __func__,
2960 use_case_table[uc_id],
2961 adev->last_logged_snd_device[uc_id][1],
2962 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2963 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2964 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2965 -1,
2966 in_snd_device,
2967 platform_get_snd_device_name(in_snd_device),
2968 platform_get_snd_device_acdb_id(in_snd_device));
2969 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2970 }
2971
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 /*
2974 * Limitation: While in call, to do a device switch we need to disable
2975 * and enable both RX and TX devices though one of them is same as current
2976 * device.
2977 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002978 if ((usecase->type == VOICE_CALL) &&
2979 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2980 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002981 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002982 }
2983
2984 if (((usecase->type == VOICE_CALL) ||
2985 (usecase->type == VOIP_CALL)) &&
2986 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2987 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302988 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002989 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002990 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002991
2992 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302993 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002994 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002995 }
2996
Aalique Grahame22e49102018-12-18 14:23:57 -08002997 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2998 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002999 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303000 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08003001 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
3002 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
3003 else
3004 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303005 }
3006
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003007 /* Disable current sound devices */
3008 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003009 disable_audio_route(adev, usecase);
3010 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 }
3012
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003013 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003014 disable_audio_route(adev, usecase);
3015 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 }
3017
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003018 /* Applicable only on the targets that has external modem.
3019 * New device information should be sent to modem before enabling
3020 * the devices to reduce in-call device switch time.
3021 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003022 if ((usecase->type == VOICE_CALL) &&
3023 (usecase->in_snd_device != SND_DEVICE_NONE) &&
3024 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003025 status = platform_switch_voice_call_enable_device_config(adev->platform,
3026 out_snd_device,
3027 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07003028 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08003029
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003030 /* Enable new sound devices */
3031 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003032 check_usecases_codec_backend(adev, usecase, out_snd_device);
Saurav Kumarc1411662020-10-14 10:50:45 +05303033 check_and_configure_headphone(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05303034 if (platform_check_codec_asrc_support(adev->platform))
3035 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003036 enable_snd_device(adev, out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003037 /* Enable haptics device for haptic usecase */
3038 if (usecase->id == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3039 enable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 }
3041
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003042 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303043 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003044 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07003045 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003046
Lakshman Chaluvarajuab7e5572020-10-28 19:29:23 +05303047 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07003048 status = platform_switch_voice_call_device_post(adev->platform,
3049 out_snd_device,
3050 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08003051
sangwoo170731f2013-06-08 15:36:36 +09003052 usecase->in_snd_device = in_snd_device;
3053 usecase->out_snd_device = out_snd_device;
3054
Dhananjay Kumard6d32152016-10-13 16:11:03 +05303055 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
3056 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05303057 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003058 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003059 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003060 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3061 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
3062 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
3063 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
3064 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
3065 /*
3066 * To best utlize DSP, check if the stream sample rate is supported/multiple of
3067 * configured device sample rate, if not update the COPP rate to be equal to the
3068 * device sample rate, else open COPP at stream sample rate
3069 */
3070 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
3071 usecase->stream.out->sample_rate,
3072 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05303073 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05303074 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
3075 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05303076 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003077 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
3078 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
3079 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3080 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003081 }
3082 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003083
Shalini Manjunatha5e610912020-12-29 13:02:25 +05303084 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3085 struct stream_in *voip_in = get_voice_communication_input(adev);
3086 struct audio_usecase *voip_in_usecase = NULL;
3087 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3088 if (voip_in != NULL &&
3089 voip_in_usecase != NULL &&
3090 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3091 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3092 (voip_in_usecase->in_snd_device ==
3093 platform_get_input_snd_device(adev->platform, voip_in,
3094 &usecase->stream.out->device_list,usecase->type))) {
3095 /*
3096 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3097 * for enabling echo-reference-voip with correct port
3098 */
3099 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3100 disable_audio_route(adev, voip_in_usecase);
3101 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3102 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3103 enable_audio_route(adev, voip_in_usecase);
3104 }
3105 }
3106
3107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003108 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003109
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003110 /* If input stream is already running then effect needs to be
3111 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003112 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003113 check_and_enable_effect(adev);
3114
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003115 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003116 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303117 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003118 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3119
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003120 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303121 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003122 voice_extn_compress_voip_is_started(adev))
3123 voice_set_sidetone(adev, out_snd_device, true);
3124 }
3125
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003126 /* Applicable only on the targets that has external modem.
3127 * Enable device command should be sent to modem only after
3128 * enabling voice call mixer controls
3129 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003130 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003131 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3132 out_snd_device,
3133 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303134
3135 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003136 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303137 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003138 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303139 if (is_bt_soc_on(adev) == false){
3140 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003141 if (in->pcm != NULL)
3142 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303143 }
3144 }
3145 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3146 && usecase->stream.out->started) {
3147 if (is_bt_soc_on(adev) == false) {
3148 ALOGD("BT SCO/A2DP disconnected while in connection");
3149 out_standby_l(&usecase->stream.out->stream.common);
3150 }
3151 }
3152 } else if ((usecase->stream.out != NULL) &&
3153 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303154 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3155 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003156 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303157 usecase->stream.out->started) {
3158 if (is_bt_soc_on(adev) == false) {
3159 ALOGD("BT SCO/A2dp disconnected while in connection");
3160 out_standby_l(&usecase->stream.out->stream.common);
3161 }
3162 }
3163 }
3164
Yung Ti Su70cb8242018-06-22 17:38:47 +08003165 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003166 struct stream_out *voip_out = voip_usecase->stream.out;
3167 audio_extn_utils_send_app_type_gain(adev,
3168 voip_out->app_type_cfg.app_type,
3169 &voip_out->app_type_cfg.gain[0]);
3170 }
3171
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07003172 ALOGV("%s: done",__func__);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 return status;
3175}
3176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177static int stop_input_stream(struct stream_in *in)
3178{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303179 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303181
3182 if (in == NULL) {
3183 ALOGE("%s: stream_in ptr is NULL", __func__);
3184 return -EINVAL;
3185 }
3186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003188 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189
Eric Laurent994a6932013-07-17 11:51:42 -07003190 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003191 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 uc_info = get_usecase_from_list(adev, in->usecase);
3193 if (uc_info == NULL) {
3194 ALOGE("%s: Could not find the usecase (%d) in the list",
3195 __func__, in->usecase);
3196 return -EINVAL;
3197 }
3198
Carter Hsu2e429db2019-05-14 18:50:52 +08003199 priority_in = get_priority_input(adev);
3200
Derek Chenea197282019-01-07 17:35:01 -08003201 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3202 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003203
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003204 /* Close in-call recording streams */
3205 voice_check_and_stop_incall_rec_usecase(adev, in);
3206
Eric Laurent150dbfe2013-02-27 14:31:02 -08003207 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003208 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003209
3210 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003211 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003213 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303214 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3215
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003216 list_remove(&uc_info->list);
3217 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Carter Hsu2e429db2019-05-14 18:50:52 +08003219 if (priority_in == in) {
3220 priority_in = get_priority_input(adev);
3221 if (priority_in)
3222 select_devices(adev, priority_in->usecase);
3223 }
3224
Vatsal Buchac09ae062018-11-14 13:25:08 +05303225 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003226 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 return ret;
3228}
3229
3230int start_input_stream(struct stream_in *in)
3231{
3232 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003233 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303235
3236 if (in == NULL) {
3237 ALOGE("%s: stream_in ptr is NULL", __func__);
3238 return -EINVAL;
3239 }
3240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003242 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003243 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244
Mingming Yin2664a5b2015-09-03 10:53:11 -07003245 if (get_usecase_from_list(adev, usecase) == NULL)
3246 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303247 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3248 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003249
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303250 if (CARD_STATUS_OFFLINE == in->card_status||
3251 CARD_STATUS_OFFLINE == adev->card_status) {
3252 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303253 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303254 goto error_config;
3255 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303256
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003257 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju87f53aa2021-02-02 15:50:11 +05303258 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303259 ALOGE("%s: SCO profile is not ready, return error", __func__);
3260 ret = -EIO;
3261 goto error_config;
3262 }
3263 }
3264
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003265 /* Check if source matches incall recording usecase criteria */
3266 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3267 if (ret)
3268 goto error_config;
3269 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003270 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3271
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303272 if (audio_extn_cin_attached_usecase(in))
3273 audio_extn_cin_acquire_usecase(in);
3274
Mingming Yin2664a5b2015-09-03 10:53:11 -07003275 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3276 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3277 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003278 ret = -EINVAL;
3279 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003280 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003281
Eric Laurentb23d5282013-05-14 15:27:20 -07003282 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 if (in->pcm_device_id < 0) {
3284 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3285 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003286 ret = -EINVAL;
3287 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003291
3292 if (!uc_info) {
3293 ret = -ENOMEM;
3294 goto error_config;
3295 }
3296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 uc_info->id = in->usecase;
3298 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003299 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003300 list_init(&uc_info->device_list);
3301 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003302 uc_info->in_snd_device = SND_DEVICE_NONE;
3303 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003305 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003306 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303307 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3308 adev->perf_lock_opts,
3309 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003310 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311
Derek Chenea197282019-01-07 17:35:01 -08003312 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3313 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003314
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303315 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3316
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303317 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303318 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303319 if (ret)
3320 goto error_open;
3321 else
3322 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003323 }
3324
Haynes Mathew George16081042017-05-31 17:16:49 -07003325 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003326 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003327 ALOGE("%s: pcm stream not ready", __func__);
3328 goto error_open;
3329 }
3330 ret = pcm_start(in->pcm);
3331 if (ret < 0) {
3332 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3333 goto error_open;
3334 }
3335 } else {
3336 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3337 unsigned int pcm_open_retry_count = 0;
3338
Zhou Song62ea0282020-03-22 19:53:01 +08003339 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3340 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003341 flags |= PCM_MMAP | PCM_NOIRQ;
3342 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3343 } else if (in->realtime) {
3344 flags |= PCM_MMAP | PCM_NOIRQ;
3345 }
3346
Garmond Leunge2433c32017-09-28 21:51:22 -07003347 if (audio_extn_ffv_get_stream() == in) {
3348 ALOGD("%s: ffv stream, update pcm config", __func__);
3349 audio_extn_ffv_update_pcm_config(&config);
3350 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003351 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3352 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3353
3354 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003355 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003356 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003357 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003358 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303359 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303360 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3361 adev->card_status = CARD_STATUS_OFFLINE;
3362 in->card_status = CARD_STATUS_OFFLINE;
3363 ret = -EIO;
3364 goto error_open;
3365 }
3366
Haynes Mathew George16081042017-05-31 17:16:49 -07003367 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3368 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3369 if (in->pcm != NULL) {
3370 pcm_close(in->pcm);
3371 in->pcm = NULL;
3372 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003373 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003374 ret = -EIO;
3375 goto error_open;
3376 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003377 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003378 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3379 continue;
3380 }
3381 break;
3382 }
3383
3384 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003385 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003386 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003387 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003388 if (ret < 0) {
3389 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3390 pcm_close(in->pcm);
3391 in->pcm = NULL;
3392 goto error_open;
3393 }
3394 register_in_stream(in);
3395 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003396 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003397 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003398 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003399 if (ret < 0) {
3400 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003401 pcm_close(in->pcm);
3402 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003403 goto error_open;
3404 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003405 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003406 }
3407
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003408 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003409 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3410 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003411
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003412 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303413 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3414
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303415done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003416 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303417 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Manisha Agarwal4c2402e2020-10-21 12:02:57 +05303418 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303419 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003420 return ret;
3421
3422error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003423 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303424 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003426
Eric Laurentc8400632013-02-14 19:04:54 -08003427error_config:
Weiyin Jiang38c0e612020-09-10 16:10:51 +08003428 if (audio_extn_cin_attached_usecase(in))
3429 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303430 /*
3431 * sleep 50ms to allow sufficient time for kernel
3432 * drivers to recover incases like SSR.
3433 */
3434 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003435 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303436 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003437 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438}
3439
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003440void lock_input_stream(struct stream_in *in)
3441{
3442 pthread_mutex_lock(&in->pre_lock);
3443 pthread_mutex_lock(&in->lock);
3444 pthread_mutex_unlock(&in->pre_lock);
3445}
3446
3447void lock_output_stream(struct stream_out *out)
3448{
3449 pthread_mutex_lock(&out->pre_lock);
3450 pthread_mutex_lock(&out->lock);
3451 pthread_mutex_unlock(&out->pre_lock);
3452}
3453
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003454/* must be called with out->lock locked */
3455static int send_offload_cmd_l(struct stream_out* out, int command)
3456{
3457 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3458
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003459 if (!cmd) {
3460 ALOGE("failed to allocate mem for command 0x%x", command);
3461 return -ENOMEM;
3462 }
3463
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464 ALOGVV("%s %d", __func__, command);
3465
3466 cmd->cmd = command;
3467 list_add_tail(&out->offload_cmd_list, &cmd->node);
3468 pthread_cond_signal(&out->offload_cond);
3469 return 0;
3470}
3471
Gautam Manam14c198b2020-12-24 14:08:04 +05303472/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473static void stop_compressed_output_l(struct stream_out *out)
3474{
Gautam Manam14c198b2020-12-24 14:08:04 +05303475 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manam14c198b2020-12-24 14:08:04 +05303477 pthread_mutex_unlock(&out->latch_lock);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08003478
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003480 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 if (out->compr != NULL) {
3482 compress_stop(out->compr);
3483 while (out->offload_thread_blocked) {
3484 pthread_cond_wait(&out->cond, &out->lock);
3485 }
3486 }
3487}
3488
Varun Balaraje49253e2017-07-06 19:48:56 +05303489bool is_interactive_usecase(audio_usecase_t uc_id)
3490{
3491 unsigned int i;
3492 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3493 if (uc_id == interactive_usecases[i])
3494 return true;
3495 }
3496 return false;
3497}
3498
3499static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3500{
3501 audio_usecase_t ret_uc = USECASE_INVALID;
3502 unsigned int intract_uc_index;
3503 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3504
3505 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3506 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3507 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3508 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3509 ret_uc = interactive_usecases[intract_uc_index];
3510 break;
3511 }
3512 }
3513
3514 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3515 return ret_uc;
3516}
3517
3518static void free_interactive_usecase(struct audio_device *adev,
3519 audio_usecase_t uc_id)
3520{
3521 unsigned int interact_uc_index;
3522 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3523
3524 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3525 if (interactive_usecases[interact_uc_index] == uc_id) {
3526 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3527 break;
3528 }
3529 }
3530 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3531}
3532
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003533bool is_offload_usecase(audio_usecase_t uc_id)
3534{
3535 unsigned int i;
3536 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3537 if (uc_id == offload_usecases[i])
3538 return true;
3539 }
3540 return false;
3541}
3542
Dhananjay Kumarac341582017-02-23 23:42:25 +05303543static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003544{
vivek mehta446c3962015-09-14 10:57:35 -07003545 audio_usecase_t ret_uc = USECASE_INVALID;
3546 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003547 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003548 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303549 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003550 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3551 else
3552 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003553
vivek mehta446c3962015-09-14 10:57:35 -07003554 pthread_mutex_lock(&adev->lock);
3555 if (get_usecase_from_list(adev, ret_uc) != NULL)
3556 ret_uc = USECASE_INVALID;
3557 pthread_mutex_unlock(&adev->lock);
3558
3559 return ret_uc;
3560 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003561
3562 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003563 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3564 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3565 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3566 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003567 break;
3568 }
3569 }
vivek mehta446c3962015-09-14 10:57:35 -07003570
3571 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3572 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003573}
3574
3575static void free_offload_usecase(struct audio_device *adev,
3576 audio_usecase_t uc_id)
3577{
vivek mehta446c3962015-09-14 10:57:35 -07003578 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003579 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003580
3581 if (!adev->multi_offload_enable)
3582 return;
3583
3584 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3585 if (offload_usecases[offload_uc_index] == uc_id) {
3586 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003587 break;
3588 }
3589 }
3590 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3591}
3592
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593static void *offload_thread_loop(void *context)
3594{
3595 struct stream_out *out = (struct stream_out *) context;
3596 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003597 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003598
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003599 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003600 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003601 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3602
3603 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003604 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003605 out->offload_state = OFFLOAD_STATE_IDLE;
3606 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003607 for (;;) {
3608 struct offload_cmd *cmd = NULL;
3609 stream_callback_event_t event;
3610 bool send_callback = false;
3611
3612 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3613 __func__, list_empty(&out->offload_cmd_list),
3614 out->offload_state);
3615 if (list_empty(&out->offload_cmd_list)) {
3616 ALOGV("%s SLEEPING", __func__);
3617 pthread_cond_wait(&out->offload_cond, &out->lock);
3618 ALOGV("%s RUNNING", __func__);
3619 continue;
3620 }
3621
3622 item = list_head(&out->offload_cmd_list);
3623 cmd = node_to_item(item, struct offload_cmd, node);
3624 list_remove(item);
3625
3626 ALOGVV("%s STATE %d CMD %d out->compr %p",
3627 __func__, out->offload_state, cmd->cmd, out->compr);
3628
3629 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3630 free(cmd);
3631 break;
3632 }
3633
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003634 // allow OFFLOAD_CMD_ERROR reporting during standby
3635 // this is needed to handle failures during compress_open
3636 // Note however that on a pause timeout, the stream is closed
3637 // and no offload usecase will be active. Therefore this
3638 // special case is needed for compress_open failures alone
3639 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3640 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003641 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003642 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003643 pthread_cond_signal(&out->cond);
3644 continue;
3645 }
3646 out->offload_thread_blocked = true;
3647 pthread_mutex_unlock(&out->lock);
3648 send_callback = false;
3649 switch(cmd->cmd) {
3650 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003651 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003653 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 send_callback = true;
3655 event = STREAM_CBK_EVENT_WRITE_READY;
3656 break;
3657 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003658 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303659 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003660 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303661 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003662 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303663 if (ret < 0)
3664 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303665 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303666 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003667 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003668 else
3669 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003670 if (-ENETRESET != ret && !(-EINTR == ret &&
3671 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303672 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303673 pthread_mutex_lock(&out->lock);
3674 out->send_new_metadata = 1;
3675 out->send_next_track_params = true;
3676 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303677 event = STREAM_CBK_EVENT_DRAIN_READY;
3678 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3679 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303680 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003681 break;
3682 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003683 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003684 ret = compress_drain(out->compr);
3685 ALOGD("copl(%p):out of compress_drain", out);
3686 // EINTR check avoids drain interruption due to SSR
3687 if (-ENETRESET != ret && !(-EINTR == ret &&
3688 CARD_STATUS_OFFLINE == out->card_status)) {
3689 send_callback = true;
3690 event = STREAM_CBK_EVENT_DRAIN_READY;
3691 } else
3692 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003693 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303694 case OFFLOAD_CMD_ERROR:
3695 ALOGD("copl(%p): sending error callback to AF", out);
3696 send_callback = true;
3697 event = STREAM_CBK_EVENT_ERROR;
3698 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003699 default:
3700 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3701 break;
3702 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003703 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003704 out->offload_thread_blocked = false;
3705 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003706 if (send_callback && out->client_callback) {
3707 ALOGVV("%s: sending client_callback event %d", __func__, event);
3708 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003709 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003710 free(cmd);
3711 }
3712
3713 pthread_cond_signal(&out->cond);
3714 while (!list_empty(&out->offload_cmd_list)) {
3715 item = list_head(&out->offload_cmd_list);
3716 list_remove(item);
3717 free(node_to_item(item, struct offload_cmd, node));
3718 }
3719 pthread_mutex_unlock(&out->lock);
3720
3721 return NULL;
3722}
3723
3724static int create_offload_callback_thread(struct stream_out *out)
3725{
3726 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3727 list_init(&out->offload_cmd_list);
3728 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3729 offload_thread_loop, out);
3730 return 0;
3731}
3732
3733static int destroy_offload_callback_thread(struct stream_out *out)
3734{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003735 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003736 stop_compressed_output_l(out);
3737 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3738
3739 pthread_mutex_unlock(&out->lock);
3740 pthread_join(out->offload_thread, (void **) NULL);
3741 pthread_cond_destroy(&out->offload_cond);
3742
3743 return 0;
3744}
3745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746static int stop_output_stream(struct stream_out *out)
3747{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303748 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 struct audio_usecase *uc_info;
3750 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003751 bool has_voip_usecase =
3752 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753
Eric Laurent994a6932013-07-17 11:51:42 -07003754 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003755 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 uc_info = get_usecase_from_list(adev, out->usecase);
3757 if (uc_info == NULL) {
3758 ALOGE("%s: Could not find the usecase (%d) in the list",
3759 __func__, out->usecase);
3760 return -EINVAL;
3761 }
3762
Zhou Songbaddf9f2020-11-20 13:57:39 +08003763 out->a2dp_muted = false;
3764
Derek Chenea197282019-01-07 17:35:01 -08003765 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3766 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003767
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003768 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303769 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003770 if (adev->visualizer_stop_output != NULL)
3771 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003772
3773 audio_extn_dts_remove_state_notifier_node(out->usecase);
3774
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003775 if (adev->offload_effects_stop_output != NULL)
3776 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003777 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3778 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3779 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003780 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003781
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003782 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3783 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003784 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003785 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003786
Eric Laurent150dbfe2013-02-27 14:31:02 -08003787 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003788 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003789
3790 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003791 disable_snd_device(adev, uc_info->out_snd_device);
Zhou Songd9bd9302020-08-04 16:34:45 +08003792 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
3793 disable_snd_device(adev, SND_DEVICE_OUT_HAPTICS);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794
Aalique Grahame22e49102018-12-18 14:23:57 -08003795 audio_extn_extspk_update(adev->extspk);
3796
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003797 if (is_offload_usecase(out->usecase)) {
3798 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3799 adev->dsp_bit_width_enforce_mode,
3800 false);
3801 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003802 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003803 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3804 false);
3805
3806 if (ret != 0)
3807 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3808 /* default service interval was successfully updated,
3809 reopen USB backend with new service interval */
3810 ret = 0;
3811 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003812
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003813 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303814 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003815 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303816 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003817 ALOGV("Disable passthrough , reset mixer to pcm");
3818 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003819#ifdef AUDIO_GKI_ENABLED
3820 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3821 out->compr_config.codec->reserved[0] = 0;
3822#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003823 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003824#endif
Mingming Yin21854652016-04-13 11:54:02 -07003825 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003826 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3827 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003828
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303829 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003830 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303831 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303832
Manish Dewangan21a850a2017-08-14 12:03:55 +05303833 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003834 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3835 if (ret < 0)
3836 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3837 }
3838
Zhou Song642ec432020-12-23 16:11:10 +08003839 /* trigger voip input to reroute when voip output changes to hearing aid */
Aalique Grahame22e49102018-12-18 14:23:57 -08003840 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003841 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003842 struct listnode *node;
3843 struct audio_usecase *usecase;
3844 list_for_each(node, &adev->usecase_list) {
3845 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Song642ec432020-12-23 16:11:10 +08003846 if (usecase->type == PCM_PLAYBACK || usecase == uc_info ||
3847 (usecase->type == PCM_CAPTURE &&
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05303848 usecase->id != USECASE_AUDIO_RECORD_VOIP &&
Zhou Song642ec432020-12-23 16:11:10 +08003849 usecase->id != USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY))
Aalique Grahame22e49102018-12-18 14:23:57 -08003850 continue;
3851
3852 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3853 __func__, usecase->id, use_case_table[usecase->id],
3854 out->usecase, use_case_table[out->usecase]);
3855 select_devices(adev, usecase->id);
3856 }
3857 }
3858
Garmond Leung5fd0b552018-04-17 11:56:12 -07003859 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003860 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 return ret;
3862}
3863
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003864struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3865 unsigned int flags, unsigned int pcm_open_retry_count,
3866 struct pcm_config *config)
3867{
3868 struct pcm* pcm = NULL;
3869
3870 while (1) {
3871 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3872 if (pcm == NULL || !pcm_is_ready(pcm)) {
3873 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3874 if (pcm != NULL) {
3875 pcm_close(pcm);
3876 pcm = NULL;
3877 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003878 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003879 return NULL;
3880
Weiyin Jiang72197252019-10-09 11:49:32 +08003881 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3883 continue;
3884 }
3885 break;
3886 }
3887
3888 if (pcm_is_ready(pcm)) {
3889 int ret = pcm_prepare(pcm);
3890 if (ret < 0) {
3891 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3892 pcm_close(pcm);
3893 pcm = NULL;
3894 }
3895 }
3896
3897 return pcm;
3898}
3899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900int start_output_stream(struct stream_out *out)
3901{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 struct audio_usecase *uc_info;
3904 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003905 char mixer_ctl_name[128];
3906 struct mixer_ctl *ctl = NULL;
3907 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303908 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003909 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910
Haynes Mathew George380745d2017-10-04 15:27:45 -07003911 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003912 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3913 ret = -EINVAL;
3914 goto error_config;
3915 }
3916
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003917 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303918 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003919 get_device_types(&out->device_list), is_haptic_usecase);
3920
3921 bool is_speaker_active = compare_device_type(&out->device_list,
3922 AUDIO_DEVICE_OUT_SPEAKER);
3923 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3924 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303925
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303926 if (CARD_STATUS_OFFLINE == out->card_status ||
3927 CARD_STATUS_OFFLINE == adev->card_status) {
3928 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303929 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003930 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303931 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303932
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003933 //Update incall music usecase to reflect correct voice session
3934 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3935 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3936 if (ret != 0) {
3937 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3938 __func__, ret);
3939 goto error_config;
3940 }
3941 }
3942
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003943 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003944 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003945 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303946 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303947 } else {
Zhou Songd01e7a22020-09-23 22:49:01 +08003948 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303949 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3950 ret = -EAGAIN;
3951 goto error_config;
3952 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303953 }
3954 }
3955 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003956 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303957 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003958 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303959 //combo usecase just by pass a2dp
3960 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003961 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303962 } else {
3963 ALOGE("%s: SCO profile is not ready, return error", __func__);
3964 ret = -EAGAIN;
3965 goto error_config;
3966 }
3967 }
3968 }
3969
Eric Laurentb23d5282013-05-14 15:27:20 -07003970 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 if (out->pcm_device_id < 0) {
3972 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3973 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003974 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003975 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 }
3977
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003978 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003979 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3980 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003981 if (adev->haptic_pcm_device_id < 0) {
3982 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3983 __func__, adev->haptic_pcm_device_id, out->usecase);
3984 ret = -EINVAL;
3985 goto error_config;
3986 }
3987 }
3988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003990
3991 if (!uc_info) {
3992 ret = -ENOMEM;
3993 goto error_config;
3994 }
3995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003996 uc_info->id = out->usecase;
3997 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003998 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003999 list_init(&uc_info->device_list);
4000 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004001 uc_info->in_snd_device = SND_DEVICE_NONE;
4002 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004003
4004 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004005 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07004006 audio_extn_usb_check_and_set_svc_int(uc_info, true);
4007 /* USB backend is not reopened immediately.
4008 This is eventually done as part of select_devices */
4009 }
4010
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004011 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012
Wei Wangf7ca6c92017-11-21 14:51:20 -08004013 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304014 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4015 adev->perf_lock_opts,
4016 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304017
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004018 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05304019 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304020 if (audio_extn_passthru_is_enabled() &&
4021 audio_extn_passthru_is_passthrough_stream(out)) {
4022 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304023 }
4024 }
4025
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004026 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004027 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304028 if (!a2dp_combo) {
4029 check_a2dp_restore_l(adev, out, false);
4030 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004031 struct listnode dev;
4032 list_init(&dev);
4033 assign_devices(&dev, &out->device_list);
4034 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4035 reassign_device_list(&out->device_list,
4036 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08004037 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004038 reassign_device_list(&out->device_list,
4039 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304040 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004041 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304042 }
4043 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05304044 select_devices(adev, out->usecase);
4045 if (is_a2dp_out_device_type(&out->device_list) &&
4046 !adev->a2dp_started) {
4047 if (is_speaker_active || is_speaker_safe_active) {
4048 struct listnode dev;
4049 list_init(&dev);
4050 assign_devices(&dev, &out->device_list);
4051 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4052 reassign_device_list(&out->device_list,
4053 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
4054 else
4055 reassign_device_list(&out->device_list,
4056 AUDIO_DEVICE_OUT_SPEAKER, "");
4057 select_devices(adev, out->usecase);
4058 assign_devices(&out->device_list, &dev);
4059 } else {
4060 ret = -EINVAL;
4061 goto error_open;
4062 }
4063 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304064 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004065
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004066 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
4067 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07004068 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07004069 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07004070
Derek Chenea197282019-01-07 17:35:01 -08004071 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
4072 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08004073
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004074 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
4075 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07004076
4077 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07004078 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07004079 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4080 ALOGE("%s: pcm stream not ready", __func__);
4081 goto error_open;
4082 }
4083 ret = pcm_start(out->pcm);
4084 if (ret < 0) {
4085 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4086 goto error_open;
4087 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004088 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004089 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004090 unsigned int flags = PCM_OUT;
4091 unsigned int pcm_open_retry_count = 0;
4092 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4093 flags |= PCM_MMAP | PCM_NOIRQ;
4094 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004095 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004096 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004097 } else
4098 flags |= PCM_MONOTONIC;
4099
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004100 if ((adev->vr_audio_mode_enabled) &&
4101 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4102 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4103 "PCM_Dev %d Topology", out->pcm_device_id);
4104 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4105 if (!ctl) {
4106 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4107 __func__, mixer_ctl_name);
4108 } else {
4109 //if success use ULLPP
4110 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4111 __func__, mixer_ctl_name, out->pcm_device_id);
4112 //There is a still a possibility that some sessions
4113 // that request for FAST|RAW when 3D audio is active
4114 //can go through ULLPP. Ideally we expects apps to
4115 //listen to audio focus and stop concurrent playback
4116 //Also, we will look for mode flag (voice_in_communication)
4117 //before enabling the realtime flag.
4118 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4119 }
4120 }
4121
Surendar Karka91fa3682018-07-02 18:12:12 +05304122 if (out->realtime)
4123 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004124 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Surendar Karka91fa3682018-07-02 18:12:12 +05304125
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004126 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4127 flags, pcm_open_retry_count,
4128 &(out->config));
4129 if (out->pcm == NULL) {
4130 ret = -EIO;
4131 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004132 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004133
4134 if (is_haptic_usecase) {
4135 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4136 adev->haptic_pcm_device_id,
4137 flags, pcm_open_retry_count,
4138 &(adev->haptics_config));
4139 // failure to open haptics pcm shouldnt stop audio,
4140 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004141
4142 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4143 ALOGD("%s: enable haptic audio synchronization", __func__);
4144 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4145 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004146 }
4147
Surendar Karka91fa3682018-07-02 18:12:12 +05304148 if (!out->realtime)
4149 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004150 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004151
Zhou Song2b8f28f2017-09-11 10:51:38 +08004152 // apply volume for voip playback after path is set up
4153 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4154 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304155 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4156 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304157 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4158 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004159 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4160 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304161 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004162 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004163 /*
4164 * set custom channel map if:
4165 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4166 * 2. custom channel map has been set by client
4167 * else default channel map of FC/FR/FL can always be set to DSP
4168 */
4169 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4170 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Weiyin Jiang810a80d2021-01-18 16:04:31 +08004171 out->pcm_device_id, -1, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004172 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4173 adev->dsp_bit_width_enforce_mode,
4174 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004176 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004177 out->compr = compress_open(adev->snd_card,
4178 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004179 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004180 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304181 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304182 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4183 adev->card_status = CARD_STATUS_OFFLINE;
4184 out->card_status = CARD_STATUS_OFFLINE;
4185 ret = -EIO;
4186 goto error_open;
4187 }
4188
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004189 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004190 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004191 compress_close(out->compr);
4192 out->compr = NULL;
4193 ret = -EIO;
4194 goto error_open;
4195 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304196 /* compress_open sends params of the track, so reset the flag here */
4197 out->is_compr_metadata_avail = false;
4198
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004199 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004200 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004201
Fred Oh3f43e742015-03-04 18:42:34 -08004202 /* Since small bufs uses blocking writes, a write will be blocked
4203 for the default max poll time (20s) in the event of an SSR.
4204 Reduce the poll time to observe and deal with SSR faster.
4205 */
Ashish Jain5106d362016-05-11 19:23:33 +05304206 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004207 compress_set_max_poll_wait(out->compr, 1000);
4208 }
4209
Manish Dewangan69426c82017-01-30 17:35:36 +05304210 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304211 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304212
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004213 audio_extn_dts_create_state_notifier_node(out->usecase);
4214 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4215 popcount(out->channel_mask),
4216 out->playback_started);
4217
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004218#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304219 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004220 audio_extn_dolby_send_ddp_endp_params(adev);
4221#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304222 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4223 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004224 if (adev->visualizer_start_output != NULL)
4225 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4226 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304227 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004228 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004229 }
Derek Chenf13dd492018-11-13 14:53:51 -08004230
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004231 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004232 /* Update cached volume from media to offload/direct stream */
4233 struct listnode *node = NULL;
4234 list_for_each(node, &adev->active_outputs_list) {
4235 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4236 streams_output_ctxt_t,
4237 list);
4238 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4239 out->volume_l = out_ctxt->output->volume_l;
4240 out->volume_r = out_ctxt->output->volume_r;
4241 }
4242 }
4243 out_set_compr_volume(&out->stream,
4244 out->volume_l, out->volume_r);
4245 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004247
4248 if (ret == 0) {
4249 register_out_stream(out);
4250 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004251 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4252 ALOGE("%s: pcm stream not ready", __func__);
4253 goto error_open;
4254 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004255 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004256 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004257 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004258 if (ret < 0)
4259 goto error_open;
4260 }
4261 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004262 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304263 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Jaideep Sharma0fa53812020-09-17 09:00:11 +05304264 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004265
vivek mehtad15d2bf2019-05-17 13:35:10 -07004266 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4267 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4268 audio_low_latency_hint_start();
4269 }
4270
Manish Dewangan21a850a2017-08-14 12:03:55 +05304271 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004272 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004273 if (ret < 0)
4274 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4275 }
4276
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004277 // consider a scenario where on pause lower layers are tear down.
4278 // so on resume, swap mixer control need to be sent only when
4279 // backend is active, hence rather than sending from enable device
4280 // sending it from start of streamtream
4281
4282 platform_set_swap_channels(adev, true);
4283
Haynes Mathew George380745d2017-10-04 15:27:45 -07004284 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304285 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004286 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004287error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004288 if (adev->haptic_pcm) {
4289 pcm_close(adev->haptic_pcm);
4290 adev->haptic_pcm = NULL;
4291 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004292 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304293 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004295error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304296 /*
4297 * sleep 50ms to allow sufficient time for kernel
4298 * drivers to recover incases like SSR.
4299 */
4300 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004301error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004302 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304303 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004304 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004305}
4306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307static int check_input_parameters(uint32_t sample_rate,
4308 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004309 int channel_count,
4310 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004312 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304314 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4315 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4316 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004317 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004318 !audio_extn_compr_cap_format_supported(format) &&
4319 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004320 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004321
Aalique Grahame22e49102018-12-18 14:23:57 -08004322 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4323 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4324 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4325 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4326 return -EINVAL;
4327 }
4328
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004329 switch (channel_count) {
4330 case 1:
4331 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304332 case 3:
4333 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004334 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004335 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304336 case 10:
4337 case 12:
4338 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004339 break;
4340 default:
4341 ret = -EINVAL;
4342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343
4344 switch (sample_rate) {
4345 case 8000:
4346 case 11025:
4347 case 12000:
4348 case 16000:
4349 case 22050:
4350 case 24000:
4351 case 32000:
4352 case 44100:
4353 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004354 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304355 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004356 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304357 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 break;
4359 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004360 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361 }
4362
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004363 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364}
4365
Naresh Tanniru04f71882018-06-26 17:46:22 +05304366
4367/** Add a value in a list if not already present.
4368 * @return true if value was successfully inserted or already present,
4369 * false if the list is full and does not contain the value.
4370 */
4371static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4372 for (size_t i = 0; i < list_length; i++) {
4373 if (list[i] == value) return true; // value is already present
4374 if (list[i] == 0) { // no values in this slot
4375 list[i] = value;
4376 return true; // value inserted
4377 }
4378 }
4379 return false; // could not insert value
4380}
4381
4382/** Add channel_mask in supported_channel_masks if not already present.
4383 * @return true if channel_mask was successfully inserted or already present,
4384 * false if supported_channel_masks is full and does not contain channel_mask.
4385 */
4386static void register_channel_mask(audio_channel_mask_t channel_mask,
4387 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4388 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4389 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4390}
4391
4392/** Add format in supported_formats if not already present.
4393 * @return true if format was successfully inserted or already present,
4394 * false if supported_formats is full and does not contain format.
4395 */
4396static void register_format(audio_format_t format,
4397 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4398 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4399 "%s: stream can not declare supporting its format %x", __func__, format);
4400}
4401/** Add sample_rate in supported_sample_rates if not already present.
4402 * @return true if sample_rate was successfully inserted or already present,
4403 * false if supported_sample_rates is full and does not contain sample_rate.
4404 */
4405static void register_sample_rate(uint32_t sample_rate,
4406 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4407 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4408 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4409}
4410
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004411static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4412{
4413 uint32_t high = num1, low = num2, temp = 0;
4414
4415 if (!num1 || !num2)
4416 return 0;
4417
4418 if (num1 < num2) {
4419 high = num2;
4420 low = num1;
4421 }
4422
4423 while (low != 0) {
4424 temp = low;
4425 low = high % low;
4426 high = temp;
4427 }
4428 return (num1 * num2)/high;
4429}
4430
4431static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4432{
4433 uint32_t remainder = 0;
4434
4435 if (!multiplier)
4436 return num;
4437
4438 remainder = num % multiplier;
4439 if (remainder)
4440 num += (multiplier - remainder);
4441
4442 return num;
4443}
4444
Aalique Grahame22e49102018-12-18 14:23:57 -08004445static size_t get_stream_buffer_size(size_t duration_ms,
4446 uint32_t sample_rate,
4447 audio_format_t format,
4448 int channel_count,
4449 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450{
4451 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004452 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453
Aalique Grahame22e49102018-12-18 14:23:57 -08004454 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004455 if (is_low_latency)
4456 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304457
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004458 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004459 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460
Ralf Herzbd08d632018-09-28 15:50:49 +02004461 /* make sure the size is multiple of 32 bytes and additionally multiple of
4462 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004463 * At 48 kHz mono 16-bit PCM:
4464 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4465 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004466 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004467 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004468 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004469
4470 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471}
4472
Aalique Grahame22e49102018-12-18 14:23:57 -08004473static size_t get_input_buffer_size(uint32_t sample_rate,
4474 audio_format_t format,
4475 int channel_count,
4476 bool is_low_latency)
4477{
4478 /* Don't know if USB HIFI in this context so use true to be conservative */
4479 if (check_input_parameters(sample_rate, format, channel_count,
4480 true /*is_usb_hifi */) != 0)
4481 return 0;
4482
4483 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4484 sample_rate,
4485 format,
4486 channel_count,
4487 is_low_latency);
4488}
4489
Derek Chenf6318be2017-06-12 17:16:24 -04004490size_t get_output_period_size(uint32_t sample_rate,
4491 audio_format_t format,
4492 int channel_count,
4493 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304494{
4495 size_t size = 0;
4496 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4497
4498 if ((duration == 0) || (sample_rate == 0) ||
4499 (bytes_per_sample == 0) || (channel_count == 0)) {
4500 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4501 bytes_per_sample, channel_count);
4502 return -EINVAL;
4503 }
4504
4505 size = (sample_rate *
4506 duration *
4507 bytes_per_sample *
4508 channel_count) / 1000;
4509 /*
4510 * To have same PCM samples for all channels, the buffer size requires to
4511 * be multiple of (number of channels * bytes per sample)
4512 * For writes to succeed, the buffer must be written at address which is multiple of 32
4513 */
4514 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4515
4516 return (size/(channel_count * bytes_per_sample));
4517}
4518
Zhou Song48453a02018-01-10 17:50:59 +08004519static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304520{
4521 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004522 uint64_t written_frames = 0;
4523 uint64_t kernel_frames = 0;
4524 uint64_t dsp_frames = 0;
4525 uint64_t signed_frames = 0;
4526 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304527
4528 /* This adjustment accounts for buffering after app processor.
4529 * It is based on estimated DSP latency per use case, rather than exact.
4530 */
George Gao9ba8a142020-07-23 14:30:03 -07004531 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004532 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304533
Zhou Song48453a02018-01-10 17:50:59 +08004534 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004535 written_frames = out->written /
4536 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4537
Ashish Jain5106d362016-05-11 19:23:33 +05304538 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4539 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4540 * hence only estimate.
4541 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004542 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4543 kernel_frames = kernel_buffer_size /
4544 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304545
Weiyin Jiang4813da12020-05-28 00:37:28 +08004546 if (written_frames >= (kernel_frames + dsp_frames))
4547 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304548
Zhou Song48453a02018-01-10 17:50:59 +08004549 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304550 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004551 if (timestamp != NULL )
4552 *timestamp = out->writeAt;
4553 } else if (timestamp != NULL) {
4554 clock_gettime(CLOCK_MONOTONIC, timestamp);
4555 }
4556 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304557
Weiyin Jiang4813da12020-05-28 00:37:28 +08004558 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4559 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304560
4561 return actual_frames_rendered;
4562}
4563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4565{
4566 struct stream_out *out = (struct stream_out *)stream;
4567
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004568 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569}
4570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004571static int out_set_sample_rate(struct audio_stream *stream __unused,
4572 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573{
4574 return -ENOSYS;
4575}
4576
4577static size_t out_get_buffer_size(const struct audio_stream *stream)
4578{
4579 struct stream_out *out = (struct stream_out *)stream;
4580
Varun Balaraje49253e2017-07-06 19:48:56 +05304581 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304582 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304583 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304584 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4585 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4586 else
4587 return out->compr_config.fragment_size;
4588 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004589 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304590 else if (is_offload_usecase(out->usecase) &&
4591 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304592 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004593
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004594 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004595 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596}
4597
4598static uint32_t out_get_channels(const struct audio_stream *stream)
4599{
4600 struct stream_out *out = (struct stream_out *)stream;
4601
4602 return out->channel_mask;
4603}
4604
4605static audio_format_t out_get_format(const struct audio_stream *stream)
4606{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004607 struct stream_out *out = (struct stream_out *)stream;
4608
4609 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610}
4611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004612static int out_set_format(struct audio_stream *stream __unused,
4613 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614{
4615 return -ENOSYS;
4616}
4617
4618static int out_standby(struct audio_stream *stream)
4619{
4620 struct stream_out *out = (struct stream_out *)stream;
4621 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004622 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004623
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304624 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4625 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004627 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004629 if (adev->adm_deregister_stream)
4630 adev->adm_deregister_stream(adev->adm_data, out->handle);
4631
Weiyin Jiang280ea742020-09-08 20:28:22 +08004632 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004633 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004634 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004635
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004636 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004638 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4639 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304640 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004641 pthread_mutex_unlock(&adev->lock);
4642 pthread_mutex_unlock(&out->lock);
4643 ALOGD("VOIP output entered standby");
4644 return 0;
4645 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004646 if (out->pcm) {
4647 pcm_close(out->pcm);
4648 out->pcm = NULL;
4649 }
Meng Wanga09da002020-04-20 12:56:04 +08004650 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4651 if (adev->haptic_pcm) {
4652 pcm_close(adev->haptic_pcm);
4653 adev->haptic_pcm = NULL;
4654 }
4655
4656 if (adev->haptic_buffer != NULL) {
4657 free(adev->haptic_buffer);
4658 adev->haptic_buffer = NULL;
4659 adev->haptic_buffer_size = 0;
4660 }
4661 adev->haptic_pcm_device_id = 0;
4662 }
4663
Haynes Mathew George16081042017-05-31 17:16:49 -07004664 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4665 do_stop = out->playback_started;
4666 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004667
4668 if (out->mmap_shared_memory_fd >= 0) {
4669 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4670 __func__, out->mmap_shared_memory_fd);
4671 close(out->mmap_shared_memory_fd);
4672 out->mmap_shared_memory_fd = -1;
4673 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004674 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004675 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004676 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304677 out->send_next_track_params = false;
4678 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004679 out->gapless_mdata.encoder_delay = 0;
4680 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004681 if (out->compr != NULL) {
4682 compress_close(out->compr);
4683 out->compr = NULL;
4684 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004685 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004686 if (do_stop) {
4687 stop_output_stream(out);
4688 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304689 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004690 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004691 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 }
4693 pthread_mutex_unlock(&out->lock);
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004694 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695 return 0;
4696}
4697
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304698static int out_on_error(struct audio_stream *stream)
4699{
4700 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004701 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304702
4703 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004704 // always send CMD_ERROR for offload streams, this
4705 // is needed e.g. when SSR happens within compress_open
4706 // since the stream is active, offload_callback_thread is also active.
4707 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4708 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004709 }
4710 pthread_mutex_unlock(&out->lock);
4711
4712 status = out_standby(&out->stream.common);
4713
4714 lock_output_stream(out);
4715 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004716 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304717 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304718
4719 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4720 ALOGD("Setting previous card status if offline");
4721 out->prev_card_status_offline = true;
4722 }
4723
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304724 pthread_mutex_unlock(&out->lock);
4725
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004726 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304727}
4728
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304729/*
Weiyin Jiang280ea742020-09-08 20:28:22 +08004730 * standby implementation without locks, assumes that the callee already
4731 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304732 */
4733int out_standby_l(struct audio_stream *stream)
4734{
4735 struct stream_out *out = (struct stream_out *)stream;
4736 struct audio_device *adev = out->dev;
4737
4738 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4739 stream, out->usecase, use_case_table[out->usecase]);
4740
4741 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004742 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304743 if (adev->adm_deregister_stream)
4744 adev->adm_deregister_stream(adev->adm_data, out->handle);
4745
Weiyin Jiang280ea742020-09-08 20:28:22 +08004746 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304747 stop_compressed_output_l(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08004748 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304749
4750 out->standby = true;
4751 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4752 voice_extn_compress_voip_close_output_stream(stream);
4753 out->started = 0;
4754 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004755 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304756 return 0;
4757 } else if (!is_offload_usecase(out->usecase)) {
4758 if (out->pcm) {
4759 pcm_close(out->pcm);
4760 out->pcm = NULL;
4761 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004762 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4763 if (adev->haptic_pcm) {
4764 pcm_close(adev->haptic_pcm);
4765 adev->haptic_pcm = NULL;
4766 }
4767
4768 if (adev->haptic_buffer != NULL) {
4769 free(adev->haptic_buffer);
4770 adev->haptic_buffer = NULL;
4771 adev->haptic_buffer_size = 0;
4772 }
4773 adev->haptic_pcm_device_id = 0;
4774 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304775 } else {
4776 ALOGD("copl(%p):standby", out);
4777 out->send_next_track_params = false;
4778 out->is_compr_metadata_avail = false;
4779 out->gapless_mdata.encoder_delay = 0;
4780 out->gapless_mdata.encoder_padding = 0;
4781 if (out->compr != NULL) {
4782 compress_close(out->compr);
4783 out->compr = NULL;
4784 }
4785 }
4786 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004787 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304788 }
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07004789 ALOGV("%s: exit", __func__);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304790 return 0;
4791}
4792
Aalique Grahame22e49102018-12-18 14:23:57 -08004793static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794{
Aalique Grahame22e49102018-12-18 14:23:57 -08004795 struct stream_out *out = (struct stream_out *)stream;
4796
4797 // We try to get the lock for consistency,
4798 // but it isn't necessary for these variables.
4799 // If we're not in standby, we may be blocked on a write.
4800 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4801 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4802 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4803
Andy Hunga1f48fa2019-07-01 18:14:53 -07004804 char buffer[256]; // for statistics formatting
4805 if (!is_offload_usecase(out->usecase)) {
4806 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4807 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4808 }
4809
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004810 if (out->start_latency_ms.n > 0) {
4811 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4812 dprintf(fd, " Start latency ms: %s\n", buffer);
4813 }
4814
Aalique Grahame22e49102018-12-18 14:23:57 -08004815 if (locked) {
4816 pthread_mutex_unlock(&out->lock);
4817 }
4818
4819 // dump error info
4820 (void)error_log_dump(
4821 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823 return 0;
4824}
4825
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004826static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4827{
4828 int ret = 0;
4829 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004830
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004831 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004832 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004833 return -EINVAL;
4834 }
4835
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304836 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004837
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004838 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4839 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304840 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004841 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004842 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4843 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304844 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004845 }
4846
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004847 ALOGV("%s new encoder delay %u and padding %u", __func__,
4848 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4849
4850 return 0;
4851}
4852
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004853static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4854{
4855 return out == adev->primary_output || out == adev->voice_tx_output;
4856}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004857
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304858// note: this call is safe only if the stream_cb is
4859// removed first in close_output_stream (as is done now).
4860static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4861{
4862 if (!stream || !parms)
4863 return;
4864
4865 struct stream_out *out = (struct stream_out *)stream;
4866 struct audio_device *adev = out->dev;
4867
4868 card_status_t status;
4869 int card;
4870 if (parse_snd_card_status(parms, &card, &status) < 0)
4871 return;
4872
4873 pthread_mutex_lock(&adev->lock);
4874 bool valid_cb = (card == adev->snd_card);
4875 pthread_mutex_unlock(&adev->lock);
4876
4877 if (!valid_cb)
4878 return;
4879
4880 lock_output_stream(out);
4881 if (out->card_status != status)
4882 out->card_status = status;
4883 pthread_mutex_unlock(&out->lock);
4884
4885 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4886 use_case_table[out->usecase],
4887 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4888
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304889 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304890 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304891 if (voice_is_call_state_active(adev) &&
4892 out == adev->primary_output) {
4893 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4894 pthread_mutex_lock(&adev->lock);
4895 voice_stop_call(adev);
4896 adev->mode = AUDIO_MODE_NORMAL;
4897 pthread_mutex_unlock(&adev->lock);
4898 }
4899 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304900 return;
4901}
4902
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004903int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004904 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004905{
4906 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004907 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004908 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004909 bool bypass_a2dp = false;
4910 bool reconfig = false;
4911 unsigned long service_interval = 0;
4912
4913 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004914 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4915
4916 list_init(&new_devices);
4917 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004918
4919 lock_output_stream(out);
4920 pthread_mutex_lock(&adev->lock);
4921
4922 /*
4923 * When HDMI cable is unplugged the music playback is paused and
4924 * the policy manager sends routing=0. But the audioflinger continues
4925 * to write data until standby time (3sec). As the HDMI core is
4926 * turned off, the write gets blocked.
4927 * Avoid this by routing audio to speaker until standby.
4928 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004929 if (is_single_device_type_equal(&out->device_list,
4930 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004931 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004932 !audio_extn_passthru_is_passthrough_stream(out) &&
4933 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004934 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004935 }
4936 /*
4937 * When A2DP is disconnected the
4938 * music playback is paused and the policy manager sends routing=0
4939 * But the audioflinger continues to write data until standby time
4940 * (3sec). As BT is turned off, the write gets blocked.
4941 * Avoid this by routing audio to speaker until standby.
4942 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004943 if (is_a2dp_out_device_type(&out->device_list) &&
4944 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004945 !audio_extn_a2dp_source_is_ready() &&
4946 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004947 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004948 }
4949 /*
Weiyin Jiangabedea32020-12-09 12:49:19 +08004950 * When USB headset is disconnected the music playback paused
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004951 * and the policy manager send routing=0. But if the USB is connected
4952 * back before the standby time, AFE is not closed and opened
4953 * when USB is connected back. So routing to speker will guarantee
4954 * AFE reconfiguration and AFE will be opend once USB is connected again
4955 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004956 if (is_usb_out_device_type(&out->device_list) &&
4957 list_empty(&new_devices) &&
4958 !audio_extn_usb_connected(NULL)) {
4959 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4960 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004961 /* To avoid a2dp to sco overlapping / BT device improper state
4962 * check with BT lib about a2dp streaming support before routing
4963 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004964 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004965 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004966 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4967 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004968 //combo usecase just by pass a2dp
4969 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4970 bypass_a2dp = true;
4971 } else {
4972 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4973 /* update device to a2dp and don't route as BT returned error
4974 * However it is still possible a2dp routing called because
4975 * of current active device disconnection (like wired headset)
4976 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004977 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004978 pthread_mutex_unlock(&adev->lock);
4979 pthread_mutex_unlock(&out->lock);
4980 goto error;
4981 }
4982 }
4983 }
4984
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004985 // Workaround: If routing to an non existing usb device, fail gracefully
4986 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004987 if (is_usb_out_device_type(&new_devices)) {
4988 struct str_parms *parms =
4989 str_parms_create_str(get_usb_device_address(&new_devices));
4990 if (!parms)
4991 goto error;
Weiyin Jiangabedea32020-12-09 12:49:19 +08004992 if (!audio_extn_usb_connected(NULL)) {
4993 ALOGW("%s: ignoring rerouting to non existing USB card", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004994 pthread_mutex_unlock(&adev->lock);
4995 pthread_mutex_unlock(&out->lock);
4996 str_parms_destroy(parms);
4997 ret = -ENOSYS;
4998 goto error;
4999 }
5000 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005001 }
5002
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08005003 // Workaround: If routing to an non existing hdmi device, fail gracefully
5004 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5005 (platform_get_edid_info_v2(adev->platform,
5006 out->extconn.cs.controller,
5007 out->extconn.cs.stream) != 0)) {
5008 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
5009 pthread_mutex_unlock(&adev->lock);
5010 pthread_mutex_unlock(&out->lock);
5011 ret = -ENOSYS;
5012 goto error;
5013 }
5014
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005015 /*
5016 * select_devices() call below switches all the usecases on the same
5017 * backend to the new device. Refer to check_usecases_codec_backend() in
5018 * the select_devices(). But how do we undo this?
5019 *
5020 * For example, music playback is active on headset (deep-buffer usecase)
5021 * and if we go to ringtones and select a ringtone, low-latency usecase
5022 * will be started on headset+speaker. As we can't enable headset+speaker
5023 * and headset devices at the same time, select_devices() switches the music
5024 * playback to headset+speaker while starting low-lateny usecase for ringtone.
5025 * So when the ringtone playback is completed, how do we undo the same?
5026 *
5027 * We are relying on the out_set_parameters() call on deep-buffer output,
5028 * once the ringtone playback is ended.
5029 * NOTE: We should not check if the current devices are same as new devices.
5030 * Because select_devices() must be called to switch back the music
5031 * playback to headset.
5032 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005033 if (!list_empty(&new_devices)) {
5034 bool same_dev = compare_devices(&out->device_list, &new_devices);
5035 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005036
5037 if (output_drives_call(adev, out)) {
5038 if (!voice_is_call_state_active(adev)) {
5039 if (adev->mode == AUDIO_MODE_IN_CALL) {
5040 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005041 ret = voice_start_call(adev);
5042 }
5043 } else {
Kunlei Zhang253ad102020-10-14 16:21:28 +08005044 platform_is_volume_boost_supported_device(adev->platform, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005045 adev->current_call_output = out;
5046 voice_update_devices_for_all_voice_usecases(adev);
5047 }
5048 }
5049
Mingshu Pang971ff702020-09-09 15:28:22 +08005050 if (is_usb_out_device_type(&out->device_list)) {
5051 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
5052 audio_extn_usb_set_service_interval(true /*playback*/,
5053 service_interval,
5054 &reconfig);
5055 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
5056 }
5057
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005058 if (!out->standby) {
5059 if (!same_dev) {
5060 ALOGV("update routing change");
5061 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
5062 adev->perf_lock_opts,
5063 adev->perf_lock_opts_size);
5064 if (adev->adm_on_routing_change)
5065 adev->adm_on_routing_change(adev->adm_data,
5066 out->handle);
5067 }
5068 if (!bypass_a2dp) {
5069 select_devices(adev, out->usecase);
5070 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005071 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
5072 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005073 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005074 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005075 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005076 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005077 }
5078
5079 if (!same_dev) {
5080 // on device switch force swap, lower functions will make sure
5081 // to check if swap is allowed or not.
5082 platform_set_swap_channels(adev, true);
5083 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5084 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005085 pthread_mutex_lock(&out->latch_lock);
5086 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5087 if (out->a2dp_muted) {
5088 out->a2dp_muted = false;
5089 if (is_offload_usecase(out->usecase))
5090 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5091 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5092 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiang280ea742020-09-08 20:28:22 +08005093 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005094 }
Zhou Songbaddf9f2020-11-20 13:57:39 +08005095 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5096 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5097 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005098 }
5099 }
5100
5101 pthread_mutex_unlock(&adev->lock);
5102 pthread_mutex_unlock(&out->lock);
5103
5104 /*handles device and call state changes*/
5105 audio_extn_extspk_update(adev->extspk);
5106
5107error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005108 ALOGV("%s: exit: code(%d)", __func__, ret);
5109 return ret;
5110}
5111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5113{
5114 struct stream_out *out = (struct stream_out *)stream;
5115 struct audio_device *adev = out->dev;
5116 struct str_parms *parms;
5117 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005118 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005119 int ext_controller = -1;
5120 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121
sangwoobc677242013-08-08 16:53:43 +09005122 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005123 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005124 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305125 if (!parms)
5126 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005127
5128 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5129 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005130 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005131 out->extconn.cs.controller = ext_controller;
5132 out->extconn.cs.stream = ext_stream;
5133 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5134 use_case_table[out->usecase], out->extconn.cs.controller,
5135 out->extconn.cs.stream);
5136 }
5137
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005138 if (out == adev->primary_output) {
5139 pthread_mutex_lock(&adev->lock);
5140 audio_extn_set_parameters(adev, parms);
5141 pthread_mutex_unlock(&adev->lock);
5142 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005143 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005144 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005145 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005146
5147 audio_extn_dts_create_state_notifier_node(out->usecase);
5148 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5149 popcount(out->channel_mask),
5150 out->playback_started);
5151
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005152 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005153 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005154
Surendar Karkaf51b5842018-04-26 11:28:38 +05305155 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5156 sizeof(value));
5157 if (err >= 0) {
5158 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5159 audio_extn_send_dual_mono_mixing_coefficients(out);
5160 }
5161
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305162 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5163 if (err >= 0) {
5164 strlcpy(out->profile, value, sizeof(out->profile));
5165 ALOGV("updating stream profile with value '%s'", out->profile);
5166 lock_output_stream(out);
5167 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5168 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005169 &out->device_list, out->flags,
5170 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305171 out->sample_rate, out->bit_width,
5172 out->channel_mask, out->profile,
5173 &out->app_type_cfg);
5174 pthread_mutex_unlock(&out->lock);
5175 }
5176
Alexy Joseph98988832017-01-13 14:56:59 -08005177 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005178 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5179 // and vendor.audio.hal.output.suspend.supported is set to true
5180 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005181 //check suspend parameter only for low latency and if the property
5182 //is enabled
5183 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5184 ALOGI("%s: got suspend_playback %s", __func__, value);
5185 lock_output_stream(out);
5186 if (!strncmp(value, "false", 5)) {
5187 //suspend_playback=false is supposed to set QOS value back to 75%
5188 //the mixer control sent with value Enable will achieve that
5189 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5190 } else if (!strncmp (value, "true", 4)) {
5191 //suspend_playback=true is supposed to remove QOS value
5192 //resetting the mixer control will set the default value
5193 //for the mixer control which is Disable and this removes the QOS vote
5194 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5195 } else {
5196 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5197 " got %s", __func__, value);
5198 ret = -1;
5199 }
5200
5201 if (ret != 0) {
5202 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5203 __func__, out->pm_qos_mixer_path, ret);
5204 }
5205
5206 pthread_mutex_unlock(&out->lock);
5207 }
5208 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005209
Alexy Joseph98988832017-01-13 14:56:59 -08005210 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305212error:
Eric Laurent994a6932013-07-17 11:51:42 -07005213 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 return ret;
5215}
5216
Paul McLeana50b7332018-12-17 08:24:21 -07005217static int in_set_microphone_direction(const struct audio_stream_in *stream,
5218 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005219 struct stream_in *in = (struct stream_in *)stream;
5220
5221 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5222
5223 in->direction = dir;
5224
5225 if (in->standby)
5226 return 0;
5227
5228 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005229}
5230
5231static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005232 struct stream_in *in = (struct stream_in *)stream;
5233
5234 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5235
5236 if (zoom > 1.0 || zoom < -1.0)
5237 return -EINVAL;
5238
5239 in->zoom = zoom;
5240
5241 if (in->standby)
5242 return 0;
5243
5244 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005245}
5246
5247
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005248static bool stream_get_parameter_channels(struct str_parms *query,
5249 struct str_parms *reply,
5250 audio_channel_mask_t *supported_channel_masks) {
5251 int ret = -1;
5252 char value[512];
5253 bool first = true;
5254 size_t i, j;
5255
5256 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5257 ret = 0;
5258 value[0] = '\0';
5259 i = 0;
5260 while (supported_channel_masks[i] != 0) {
5261 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5262 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5263 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305264 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005265
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305266 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005267 first = false;
5268 break;
5269 }
5270 }
5271 i++;
5272 }
5273 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5274 }
5275 return ret == 0;
5276}
5277
5278static bool stream_get_parameter_formats(struct str_parms *query,
5279 struct str_parms *reply,
5280 audio_format_t *supported_formats) {
5281 int ret = -1;
5282 char value[256];
5283 size_t i, j;
5284 bool first = true;
5285
5286 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5287 ret = 0;
5288 value[0] = '\0';
5289 i = 0;
5290 while (supported_formats[i] != 0) {
5291 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5292 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5293 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305294 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005295 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305296 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005297 first = false;
5298 break;
5299 }
5300 }
5301 i++;
5302 }
5303 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5304 }
5305 return ret == 0;
5306}
5307
5308static bool stream_get_parameter_rates(struct str_parms *query,
5309 struct str_parms *reply,
5310 uint32_t *supported_sample_rates) {
5311
5312 int i;
5313 char value[256];
5314 int ret = -1;
5315 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5316 ret = 0;
5317 value[0] = '\0';
5318 i=0;
5319 int cursor = 0;
5320 while (supported_sample_rates[i]) {
5321 int avail = sizeof(value) - cursor;
5322 ret = snprintf(value + cursor, avail, "%s%d",
5323 cursor > 0 ? "|" : "",
5324 supported_sample_rates[i]);
5325 if (ret < 0 || ret >= avail) {
5326 // if cursor is at the last element of the array
5327 // overwrite with \0 is duplicate work as
5328 // snprintf already put a \0 in place.
5329 // else
5330 // we had space to write the '|' at value[cursor]
5331 // (which will be overwritten) or no space to fill
5332 // the first element (=> cursor == 0)
5333 value[cursor] = '\0';
5334 break;
5335 }
5336 cursor += ret;
5337 ++i;
5338 }
5339 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5340 value);
5341 }
5342 return ret >= 0;
5343}
5344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005345static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5346{
5347 struct stream_out *out = (struct stream_out *)stream;
5348 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005349 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005350 char value[256];
5351 struct str_parms *reply = str_parms_create();
5352 size_t i, j;
5353 int ret;
5354 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005355
5356 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005357 if (reply) {
5358 str_parms_destroy(reply);
5359 }
5360 if (query) {
5361 str_parms_destroy(query);
5362 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005363 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5364 return NULL;
5365 }
5366
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005367 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005368 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5369 if (ret >= 0) {
5370 value[0] = '\0';
5371 i = 0;
5372 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005373 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5374 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005376 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005377 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005378 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379 first = false;
5380 break;
5381 }
5382 }
5383 i++;
5384 }
5385 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5386 str = str_parms_to_str(reply);
5387 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005388 voice_extn_out_get_parameters(out, query, reply);
5389 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005390 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005391
Alexy Joseph62142aa2015-11-16 15:10:34 -08005392
5393 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5394 if (ret >= 0) {
5395 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305396 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5397 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005398 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305399 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005400 } else {
5401 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305402 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005403 }
5404 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005405 if (str)
5406 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005407 str = str_parms_to_str(reply);
5408 }
5409
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005410 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5411 if (ret >= 0) {
5412 value[0] = '\0';
5413 i = 0;
5414 first = true;
5415 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005416 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5417 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005418 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005419 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005420 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005421 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005422 first = false;
5423 break;
5424 }
5425 }
5426 i++;
5427 }
5428 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005429 if (str)
5430 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005431 str = str_parms_to_str(reply);
5432 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005433
5434 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5435 if (ret >= 0) {
5436 value[0] = '\0';
5437 i = 0;
5438 first = true;
5439 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005440 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5441 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005442 if (!first) {
5443 strlcat(value, "|", sizeof(value));
5444 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005445 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005446 first = false;
5447 break;
5448 }
5449 }
5450 i++;
5451 }
5452 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5453 if (str)
5454 free(str);
5455 str = str_parms_to_str(reply);
5456 }
5457
Alexy Joseph98988832017-01-13 14:56:59 -08005458 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5459 //only low latency track supports suspend_resume
5460 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005461 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005462 if (str)
5463 free(str);
5464 str = str_parms_to_str(reply);
5465 }
5466
5467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 str_parms_destroy(query);
5469 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005470 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005471 return str;
5472}
5473
5474static uint32_t out_get_latency(const struct audio_stream_out *stream)
5475{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005476 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005478 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005479
Alexy Josephaa54c872014-12-03 02:46:47 -08005480 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305481 lock_output_stream(out);
5482 latency = audio_extn_utils_compress_get_dsp_latency(out);
5483 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005484 } else if ((out->realtime) ||
5485 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005486 // since the buffer won't be filled up faster than realtime,
5487 // return a smaller number
5488 if (out->config.rate)
5489 period_ms = (out->af_period_multiplier * out->config.period_size *
5490 1000) / (out->config.rate);
5491 else
5492 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005493 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005494 } else {
5495 latency = (out->config.period_count * out->config.period_size * 1000) /
Mingshu Pangf69a88d2021-04-30 16:14:39 +08005496 (out->config.rate);
5497 if (out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)
5498 latency += platform_render_latency(out)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005499 }
5500
Zhou Songd2537a02020-06-11 22:04:46 +08005501 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005502 latency += audio_extn_a2dp_get_encoder_latency();
5503
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305504 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005505 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005506}
5507
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305508static float AmpToDb(float amplification)
5509{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305510 float db = DSD_VOLUME_MIN_DB;
5511 if (amplification > 0) {
5512 db = 20 * log10(amplification);
5513 if(db < DSD_VOLUME_MIN_DB)
5514 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305515 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305516 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305517}
5518
Arun Mirpuri5d170872019-03-26 13:21:31 -07005519static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5520 float right)
5521{
5522 struct stream_out *out = (struct stream_out *)stream;
5523 long volume = 0;
5524 char mixer_ctl_name[128] = "";
5525 struct audio_device *adev = out->dev;
5526 struct mixer_ctl *ctl = NULL;
5527 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5528 PCM_PLAYBACK);
5529
5530 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5531 "Playback %d Volume", pcm_device_id);
5532 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5533 if (!ctl) {
5534 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5535 __func__, mixer_ctl_name);
5536 return -EINVAL;
5537 }
5538 if (left != right)
5539 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5540 __func__, left, right);
5541 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5542 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5543 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5544 __func__, mixer_ctl_name, volume);
5545 return -EINVAL;
5546 }
5547 return 0;
5548}
5549
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305550static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5551 float right)
5552{
5553 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305554 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305555 char mixer_ctl_name[128];
5556 struct audio_device *adev = out->dev;
5557 struct mixer_ctl *ctl;
5558 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5559 PCM_PLAYBACK);
5560
5561 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5562 "Compress Playback %d Volume", pcm_device_id);
5563 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5564 if (!ctl) {
5565 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5566 __func__, mixer_ctl_name);
5567 return -EINVAL;
5568 }
5569 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5570 __func__, mixer_ctl_name, left, right);
5571 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5572 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5573 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5574
5575 return 0;
5576}
5577
Zhou Song2b8f28f2017-09-11 10:51:38 +08005578static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5579 float right)
5580{
5581 struct stream_out *out = (struct stream_out *)stream;
5582 char mixer_ctl_name[] = "App Type Gain";
5583 struct audio_device *adev = out->dev;
5584 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305585 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005586
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005587 if (!is_valid_volume(left, right)) {
5588 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5589 __func__, left, right);
5590 return -EINVAL;
5591 }
5592
Zhou Song2b8f28f2017-09-11 10:51:38 +08005593 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5594 if (!ctl) {
5595 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5596 __func__, mixer_ctl_name);
5597 return -EINVAL;
5598 }
5599
5600 set_values[0] = 0; //0: Rx Session 1:Tx Session
5601 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305602 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5603 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005604
5605 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5606 return 0;
5607}
5608
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305609static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5610 float right)
5611{
5612 struct stream_out *out = (struct stream_out *)stream;
5613 /* Volume control for pcm playback */
5614 if (left != right) {
5615 return -EINVAL;
5616 } else {
5617 char mixer_ctl_name[128];
5618 struct audio_device *adev = out->dev;
5619 struct mixer_ctl *ctl;
5620 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5621 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5622 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5623 if (!ctl) {
5624 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5625 return -EINVAL;
5626 }
5627
5628 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5629 int ret = mixer_ctl_set_value(ctl, 0, volume);
5630 if (ret < 0) {
5631 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5632 return -EINVAL;
5633 }
5634
5635 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5636
5637 return 0;
5638 }
5639}
5640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641static int out_set_volume(struct audio_stream_out *stream, float left,
5642 float right)
5643{
Eric Laurenta9024de2013-04-04 09:19:12 -07005644 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005645 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305646 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005647
Arun Mirpuri5d170872019-03-26 13:21:31 -07005648 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005649 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5650 /* only take left channel into account: the API is for stereo anyway */
5651 out->muted = (left == 0.0f);
5652 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005653 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305654 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005655 /*
5656 * Set mute or umute on HDMI passthrough stream.
5657 * Only take left channel into account.
5658 * Mute is 0 and unmute 1
5659 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305660 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305661 } else if (out->format == AUDIO_FORMAT_DSD){
5662 char mixer_ctl_name[128] = "DSD Volume";
5663 struct audio_device *adev = out->dev;
5664 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5665
5666 if (!ctl) {
5667 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5668 __func__, mixer_ctl_name);
5669 return -EINVAL;
5670 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305671 volume[0] = (long)(AmpToDb(left));
5672 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305673 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5674 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005675 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005676 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005677 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5678 struct listnode *node = NULL;
5679 list_for_each(node, &adev->active_outputs_list) {
5680 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5681 streams_output_ctxt_t,
5682 list);
5683 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5684 out->volume_l = out_ctxt->output->volume_l;
5685 out->volume_r = out_ctxt->output->volume_r;
5686 }
5687 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005688 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005689 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005690 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5691 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08005692 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005693 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005694 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +08005695 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005696 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5697 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305698 ret = out_set_compr_volume(stream, left, right);
5699 out->volume_l = left;
5700 out->volume_r = right;
Weiyin Jiang280ea742020-09-08 20:28:22 +08005701 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305702 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005703 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005704 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005705 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5706 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005707 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005708 if (!out->standby) {
5709 audio_extn_utils_send_app_type_gain(out->dev,
5710 out->app_type_cfg.app_type,
5711 &out->app_type_cfg.gain[0]);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005712 if (!out->a2dp_muted)
5713 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005714 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005715 out->volume_l = left;
5716 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005717 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005718 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005719 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5720 ALOGV("%s: MMAP set volume called", __func__);
5721 if (!out->standby)
5722 ret = out_set_mmap_volume(stream, left, right);
5723 out->volume_l = left;
5724 out->volume_r = right;
5725 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305726 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305727 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5728 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Songbaddf9f2020-11-20 13:57:39 +08005729 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305730 /* Volume control for pcm playback */
Zhou Songbaddf9f2020-11-20 13:57:39 +08005731 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305732 ret = out_set_pcm_volume(stream, left, right);
5733 else
5734 out->apply_volume = true;
5735
5736 out->volume_l = left;
5737 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005738 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305739 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005740 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5741 ALOGV("%s: bus device set volume called", __func__);
Zhou Songbaddf9f2020-11-20 13:57:39 +08005742 pthread_mutex_lock(&out->latch_lock);
5743 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005744 ret = out_set_pcm_volume(stream, left, right);
5745 out->volume_l = left;
5746 out->volume_r = right;
Zhou Songbaddf9f2020-11-20 13:57:39 +08005747 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005748 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005749 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005751 return -ENOSYS;
5752}
5753
Zhou Songc9672822017-08-16 16:01:39 +08005754static void update_frames_written(struct stream_out *out, size_t bytes)
5755{
5756 size_t bpf = 0;
5757
5758 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5759 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5760 bpf = 1;
5761 else if (!is_offload_usecase(out->usecase))
5762 bpf = audio_bytes_per_sample(out->format) *
5763 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005764
5765 pthread_mutex_lock(&out->position_query_lock);
5766 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005767 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005768 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5769 }
5770 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005771}
5772
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005773int split_and_write_audio_haptic_data(struct stream_out *out,
5774 const void *buffer, size_t bytes_to_write)
5775{
5776 struct audio_device *adev = out->dev;
5777
5778 int ret = 0;
5779 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5780 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5781 size_t frame_size = channel_count * bytes_per_sample;
5782 size_t frame_count = bytes_to_write / frame_size;
5783
5784 bool force_haptic_path =
5785 property_get_bool("vendor.audio.test_haptic", false);
5786
5787 // extract Haptics data from Audio buffer
5788 bool alloc_haptic_buffer = false;
5789 int haptic_channel_count = adev->haptics_config.channels;
5790 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5791 size_t audio_frame_size = frame_size - haptic_frame_size;
5792 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5793
5794 if (adev->haptic_buffer == NULL) {
5795 alloc_haptic_buffer = true;
5796 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5797 free(adev->haptic_buffer);
5798 adev->haptic_buffer_size = 0;
5799 alloc_haptic_buffer = true;
5800 }
5801
5802 if (alloc_haptic_buffer) {
5803 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005804 if(adev->haptic_buffer == NULL) {
5805 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5806 return -ENOMEM;
5807 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005808 adev->haptic_buffer_size = total_haptic_buffer_size;
5809 }
5810
5811 size_t src_index = 0, aud_index = 0, hap_index = 0;
5812 uint8_t *audio_buffer = (uint8_t *)buffer;
5813 uint8_t *haptic_buffer = adev->haptic_buffer;
5814
5815 // This is required for testing only. This works for stereo data only.
5816 // One channel is fed to audio stream and other to haptic stream for testing.
5817 if (force_haptic_path)
5818 audio_frame_size = haptic_frame_size = bytes_per_sample;
5819
5820 for (size_t i = 0; i < frame_count; i++) {
5821 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5822 audio_frame_size);
5823 aud_index += audio_frame_size;
5824 src_index += audio_frame_size;
5825
5826 if (adev->haptic_pcm)
5827 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5828 haptic_frame_size);
5829 hap_index += haptic_frame_size;
5830 src_index += haptic_frame_size;
5831
5832 // This is required for testing only.
5833 // Discard haptic channel data.
5834 if (force_haptic_path)
5835 src_index += haptic_frame_size;
5836 }
5837
5838 // write to audio pipeline
5839 ret = pcm_write(out->pcm, (void *)audio_buffer,
5840 frame_count * audio_frame_size);
5841
5842 // write to haptics pipeline
5843 if (adev->haptic_pcm)
5844 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5845 frame_count * haptic_frame_size);
5846
5847 return ret;
5848}
5849
Aalique Grahame22e49102018-12-18 14:23:57 -08005850#ifdef NO_AUDIO_OUT
5851static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5852 const void *buffer __unused, size_t bytes)
5853{
5854 struct stream_out *out = (struct stream_out *)stream;
5855
5856 /* No Output device supported other than BT for playback.
5857 * Sleep for the amount of buffer duration
5858 */
5859 lock_output_stream(out);
5860 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5861 (const struct audio_stream_out *)&out->stream) /
5862 out_get_sample_rate(&out->stream.common));
5863 pthread_mutex_unlock(&out->lock);
5864 return bytes;
5865}
5866#endif
5867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5869 size_t bytes)
5870{
5871 struct stream_out *out = (struct stream_out *)stream;
5872 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005873 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305874 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005875 const size_t frame_size = audio_stream_out_frame_size(stream);
5876 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305877 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005878 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879
Haynes Mathew George380745d2017-10-04 15:27:45 -07005880 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005881 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305882
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305883 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005884
Dhananjay Kumarac341582017-02-23 23:42:25 +05305885 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305886 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305887 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5888 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005889 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305890 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305891 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305892 ALOGD(" %s: sound card is not active/SSR state", __func__);
5893 ret= -EIO;
5894 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305895 }
5896 }
5897
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305898 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305899 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305900 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305901 goto exit;
5902 }
5903
Haynes Mathew George16081042017-05-31 17:16:49 -07005904 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5905 ret = -EINVAL;
5906 goto exit;
5907 }
5908
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005909 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305910 !out->is_iec61937_info_available) {
5911
5912 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5913 out->is_iec61937_info_available = true;
5914 } else if (audio_extn_passthru_is_enabled()) {
5915 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305916 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305917
5918 if((out->format == AUDIO_FORMAT_DTS) ||
5919 (out->format == AUDIO_FORMAT_DTS_HD)) {
5920 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5921 buffer, bytes);
5922 if (ret) {
5923 if (ret != -ENOSYS) {
5924 out->is_iec61937_info_available = false;
5925 ALOGD("iec61937 transmission info not yet updated retry");
5926 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305927 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305928 /* if stream has started and after that there is
5929 * stream config change (iec transmission config)
5930 * then trigger select_device to update backend configuration.
5931 */
5932 out->stream_config_changed = true;
5933 pthread_mutex_lock(&adev->lock);
5934 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305935 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005936 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305937 ret = -EINVAL;
5938 goto exit;
5939 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305940 pthread_mutex_unlock(&adev->lock);
5941 out->stream_config_changed = false;
5942 out->is_iec61937_info_available = true;
5943 }
5944 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305945
Meng Wang4c32fb42020-01-16 17:57:11 +08005946#ifdef AUDIO_GKI_ENABLED
5947 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5948 compr_passthr = out->compr_config.codec->reserved[0];
5949#else
5950 compr_passthr = out->compr_config.codec->compr_passthr;
5951#endif
5952
Garmond Leung317cbf12017-09-13 16:20:50 -07005953 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005954 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305955 (out->is_iec61937_info_available == true)) {
5956 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5957 ret = -EINVAL;
5958 goto exit;
5959 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305960 }
5961 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305962
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005963 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005964 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005965 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5966 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Songd01e7a22020-09-23 22:49:01 +08005967 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305968 ret = -EIO;
5969 goto exit;
5970 }
5971 }
5972 }
5973
Weiyin Jiangabedea32020-12-09 12:49:19 +08005974 if (is_usb_out_device_type(&out->device_list) &&
5975 !audio_extn_usb_connected(NULL)) {
5976 ret = -EIO;
5977 goto exit;
5978 }
5979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005980 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005981 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005982 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5983
Eric Laurent150dbfe2013-02-27 14:31:02 -08005984 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005985 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5986 ret = voice_extn_compress_voip_start_output_stream(out);
5987 else
5988 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005989 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005990 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005991 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005992 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005993 goto exit;
5994 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305995 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005996 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005997
5998 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005999 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006000 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05306001 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07006002 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08006003 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306004
6005 if ((out->is_iec61937_info_available == true) &&
6006 (audio_extn_passthru_is_passthrough_stream(out))&&
6007 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
6008 ret = -EINVAL;
6009 goto exit;
6010 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05306011 if (out->set_dual_mono)
6012 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006013
6014 // log startup time in ms.
6015 simple_stats_log(
6016 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006017 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006018
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006019 if (adev->is_channel_status_set == false &&
6020 compare_device_type(&out->device_list,
6021 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08006022 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05306023 adev->is_channel_status_set = true;
6024 }
6025
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306026 if ((adev->use_old_pspd_mix_ctrl == true) &&
6027 (out->pspd_coeff_sent == false)) {
6028 /*
6029 * Need to resend pspd coefficients after stream started for
6030 * older kernel version as it does not save the coefficients
6031 * and also stream has to be started for coeff to apply.
6032 */
6033 usecase = get_usecase_from_list(adev, out->usecase);
6034 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05306035 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306036 out->pspd_coeff_sent = true;
6037 }
6038 }
6039
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006040 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08006041 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006042 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006043 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006044 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
6045 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306046 if (out->send_next_track_params && out->is_compr_metadata_avail) {
6047 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08006048 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05306049 out->send_next_track_params = false;
6050 out->is_compr_metadata_avail = false;
6051 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006052 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05306053 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306054 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07006055
Ashish Jain83a6cc22016-06-28 14:34:17 +05306056 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05306057 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05306058 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05306059 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006060 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05306061 return -EINVAL;
6062 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05306063 audio_format_t dst_format = out->hal_op_format;
6064 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05306065
Dieter Luecking5d57def2018-09-07 14:23:37 +02006066 /* prevent division-by-zero */
6067 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
6068 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
6069 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
6070 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05306071 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006072 ATRACE_END();
6073 return -EINVAL;
6074 }
6075
Ashish Jainf1eaa582016-05-23 20:54:24 +05306076 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
6077 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
6078
Ashish Jain83a6cc22016-06-28 14:34:17 +05306079 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306080 dst_format,
6081 buffer,
6082 src_format,
6083 frames);
6084
Ashish Jain83a6cc22016-06-28 14:34:17 +05306085 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306086 bytes_to_write);
6087
6088 /*Convert written bytes in audio flinger format*/
6089 if (ret > 0)
6090 ret = ((ret * format_to_bitwidth_table[out->format]) /
6091 format_to_bitwidth_table[dst_format]);
6092 }
6093 } else
6094 ret = compress_write(out->compr, buffer, bytes);
6095
Zhou Songc9672822017-08-16 16:01:39 +08006096 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6097 update_frames_written(out, bytes);
6098
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306099 if (ret < 0)
6100 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006101 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306102 /*msg to cb thread only if non blocking write is enabled*/
6103 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306104 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006105 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306106 } else if (-ENETRESET == ret) {
6107 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306108 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306109 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306110 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006111 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306112 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006113 }
Ashish Jain5106d362016-05-11 19:23:33 +05306114
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306115 /* Call compr start only when non-zero bytes of data is there to be rendered */
6116 if (!out->playback_started && ret > 0) {
6117 int status = compress_start(out->compr);
6118 if (status < 0) {
6119 ret = status;
6120 ALOGE("%s: compr start failed with err %d", __func__, errno);
6121 goto exit;
6122 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006123 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006124 out->playback_started = 1;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006125 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006126 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiang280ea742020-09-08 20:28:22 +08006127 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006128
6129 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6130 popcount(out->channel_mask),
6131 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006132 }
6133 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006134 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006135 return ret;
6136 } else {
6137 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006138 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006139 if (out->muted)
6140 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006141 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6142 __func__, frames, frame_size, bytes_to_write);
6143
Aalique Grahame22e49102018-12-18 14:23:57 -08006144 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006145 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6146 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6147 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006148 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6149 int16_t *src = (int16_t *)buffer;
6150 int16_t *dst = (int16_t *)buffer;
6151
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006152 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006153 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006154 "out_write called for %s use case with wrong properties",
6155 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006156
6157 /*
6158 * FIXME: this can be removed once audio flinger mixer supports
6159 * mono output
6160 */
6161
6162 /*
6163 * Code below goes over each frame in the buffer and adds both
6164 * L and R samples and then divides by 2 to convert to mono
6165 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006166 if (channel_count == 2) {
6167 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6168 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6169 }
6170 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006171 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006172 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006173
6174 // Note: since out_get_presentation_position() is called alternating with out_write()
6175 // by AudioFlinger, we can check underruns using the prior timestamp read.
6176 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6177 if (out->last_fifo_valid) {
6178 // compute drain to see if there is an underrun.
6179 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306180 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6181 int64_t frames_by_time =
6182 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6183 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006184 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6185
6186 if (underrun > 0) {
6187 simple_stats_log(&out->fifo_underruns, underrun);
6188
6189 ALOGW("%s: underrun(%lld) "
6190 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6191 __func__,
6192 (long long)out->fifo_underruns.n,
6193 (long long)frames_by_time,
6194 (long long)out->last_fifo_frames_remaining);
6195 }
6196 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6197 }
6198
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306199 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006200
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006201 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006202
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006203 if (out->config.rate)
6204 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6205 out->config.rate;
6206
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006207 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006208 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6209
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006210 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006211 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006212 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306213 out->convert_buffer != NULL) {
6214
6215 memcpy_by_audio_format(out->convert_buffer,
6216 out->hal_op_format,
6217 buffer,
6218 out->hal_ip_format,
6219 out->config.period_size * out->config.channels);
6220
6221 ret = pcm_write(out->pcm, out->convert_buffer,
6222 (out->config.period_size *
6223 out->config.channels *
6224 format_to_bitwidth_table[out->hal_op_format]));
6225 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306226 /*
6227 * To avoid underrun in DSP when the application is not pumping
6228 * data at required rate, check for the no. of bytes and ignore
6229 * pcm_write if it is less than actual buffer size.
6230 * It is a work around to a change in compress VOIP driver.
6231 */
6232 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6233 bytes < (out->config.period_size * out->config.channels *
6234 audio_bytes_per_sample(out->format))) {
6235 size_t voip_buf_size =
6236 out->config.period_size * out->config.channels *
6237 audio_bytes_per_sample(out->format);
6238 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6239 __func__, bytes, voip_buf_size);
6240 usleep(((uint64_t)voip_buf_size - bytes) *
6241 1000000 / audio_stream_out_frame_size(stream) /
6242 out_get_sample_rate(&out->stream.common));
6243 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006244 } else {
6245 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6246 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6247 else
6248 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6249 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306250 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006251
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006252 release_out_focus(out);
6253
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306254 if (ret < 0)
6255 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006256 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306257 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006259 }
6260
6261exit:
Zhou Songc9672822017-08-16 16:01:39 +08006262 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306263 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306264 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306265 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 pthread_mutex_unlock(&out->lock);
6267
6268 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006269 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006270 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306271 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306272 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306273 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306274 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306275 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306276 out->standby = true;
6277 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306278 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006279 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6280 /* prevent division-by-zero */
6281 uint32_t stream_size = audio_stream_out_frame_size(stream);
6282 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006283
Dieter Luecking5d57def2018-09-07 14:23:37 +02006284 if ((stream_size == 0) || (srate == 0)) {
6285 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6286 ATRACE_END();
6287 return -EINVAL;
6288 }
6289 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6290 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006291 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306292 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006293 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006294 return ret;
6295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006296 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006297 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298 return bytes;
6299}
6300
6301static int out_get_render_position(const struct audio_stream_out *stream,
6302 uint32_t *dsp_frames)
6303{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006304 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006305
6306 if (dsp_frames == NULL)
6307 return -EINVAL;
6308
6309 *dsp_frames = 0;
6310 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006311 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306312
6313 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6314 * this operation and adev_close_output_stream(where out gets reset).
6315 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306316 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006317 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306318 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006319 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306320 return 0;
6321 }
6322
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006323 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306324 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306325 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006326 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306327 if (ret < 0)
6328 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006329 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306330 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006331 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306332 if (-ENETRESET == ret) {
6333 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306334 out->card_status = CARD_STATUS_OFFLINE;
6335 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306336 } else if(ret < 0) {
6337 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306338 ret = -EINVAL;
6339 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306340 /*
6341 * Handle corner case where compress session is closed during SSR
6342 * and timestamp is queried
6343 */
6344 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306345 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306346 } else if (out->prev_card_status_offline) {
6347 ALOGE("ERROR: previously sound card was offline,return error");
6348 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306349 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306350 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006351 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306352 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306353 pthread_mutex_unlock(&out->lock);
6354 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006355 } else if (audio_is_linear_pcm(out->format)) {
6356 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006357 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006358 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006359 } else
6360 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006361}
6362
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006363static int out_add_audio_effect(const struct audio_stream *stream __unused,
6364 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006365{
6366 return 0;
6367}
6368
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006369static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6370 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006371{
6372 return 0;
6373}
6374
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006375static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6376 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006377{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306378 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006379}
6380
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006381static int out_get_presentation_position(const struct audio_stream_out *stream,
6382 uint64_t *frames, struct timespec *timestamp)
6383{
6384 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306385 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006386 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006387
Ashish Jain5106d362016-05-11 19:23:33 +05306388 /* below piece of code is not guarded against any lock because audioFliner serializes
6389 * this operation and adev_close_output_stream( where out gets reset).
6390 */
6391 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306392 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006393 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306394 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6395 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6396 return 0;
6397 }
6398
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006399 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006400
Ashish Jain5106d362016-05-11 19:23:33 +05306401 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6402 ret = compress_get_tstamp(out->compr, &dsp_frames,
6403 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006404 // Adjustment accounts for A2dp encoder latency with offload usecases
6405 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006406 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006407 unsigned long offset =
6408 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6409 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6410 }
Ashish Jain5106d362016-05-11 19:23:33 +05306411 ALOGVV("%s rendered frames %ld sample_rate %d",
6412 __func__, dsp_frames, out->sample_rate);
6413 *frames = dsp_frames;
6414 if (ret < 0)
6415 ret = -errno;
6416 if (-ENETRESET == ret) {
6417 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306418 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306419 ret = -EINVAL;
6420 } else
6421 ret = 0;
6422 /* this is the best we can do */
6423 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006424 } else {
6425 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006426 unsigned int avail;
6427 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006428 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006429 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006430
Andy Hunga1f48fa2019-07-01 18:14:53 -07006431 if (out->kernel_buffer_size > avail) {
6432 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6433 } else {
6434 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6435 __func__, avail, out->kernel_buffer_size);
6436 avail = out->kernel_buffer_size;
6437 frames_temp = out->last_fifo_frames_remaining = 0;
6438 }
6439 out->last_fifo_valid = true;
6440 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6441
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006442 if (out->written >= frames_temp)
6443 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006444
Andy Hunga1f48fa2019-07-01 18:14:53 -07006445 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6446 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6447
Weiyin Jiangd4633762018-03-16 12:05:03 +08006448 // This adjustment accounts for buffering after app processor.
6449 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006450 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006451 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006452 if (signed_frames >= frames_temp)
6453 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006454
Weiyin Jiangd4633762018-03-16 12:05:03 +08006455 // Adjustment accounts for A2dp encoder latency with non offload usecases
6456 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006457 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006458 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6459 if (signed_frames >= frames_temp)
6460 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006461 }
6462
6463 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006464 *frames = signed_frames;
6465 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006466 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006467 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6468 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006469 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306470 *frames = out->written;
6471 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306472 if (is_offload_usecase(out->usecase))
6473 ret = -EINVAL;
6474 else
6475 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006476 }
6477 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006478 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006479 return ret;
6480}
6481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006482static int out_set_callback(struct audio_stream_out *stream,
6483 stream_callback_t callback, void *cookie)
6484{
6485 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006486 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006487
6488 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006489 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006490 out->client_callback = callback;
6491 out->client_cookie = cookie;
6492 if (out->adsp_hdlr_stream_handle) {
6493 ret = audio_extn_adsp_hdlr_stream_set_callback(
6494 out->adsp_hdlr_stream_handle,
6495 callback,
6496 cookie);
6497 if (ret)
6498 ALOGW("%s:adsp hdlr callback registration failed %d",
6499 __func__, ret);
6500 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006501 pthread_mutex_unlock(&out->lock);
6502 return 0;
6503}
6504
6505static int out_pause(struct audio_stream_out* stream)
6506{
6507 struct stream_out *out = (struct stream_out *)stream;
6508 int status = -ENOSYS;
6509 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006510 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006511 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306512 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006513 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006514 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006515 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306516 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306517 status = compress_pause(out->compr);
6518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006519 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006520
Mingming Yin21854652016-04-13 11:54:02 -07006521 if (audio_extn_passthru_is_active()) {
6522 ALOGV("offload use case, pause passthru");
6523 audio_extn_passthru_on_pause(out);
6524 }
6525
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306526 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006527 audio_extn_dts_notify_playback_state(out->usecase, 0,
6528 out->sample_rate, popcount(out->channel_mask),
6529 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006530 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006531 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006532 pthread_mutex_unlock(&out->lock);
6533 }
6534 return status;
6535}
6536
6537static int out_resume(struct audio_stream_out* stream)
6538{
6539 struct stream_out *out = (struct stream_out *)stream;
6540 int status = -ENOSYS;
6541 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006542 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006543 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306544 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006545 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006546 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006547 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306548 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306549 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006550 }
6551 if (!status) {
6552 out->offload_state = OFFLOAD_STATE_PLAYING;
6553 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306554 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006555 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6556 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006557 }
Weiyin Jiang280ea742020-09-08 20:28:22 +08006558 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006559 pthread_mutex_unlock(&out->lock);
6560 }
6561 return status;
6562}
6563
6564static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6565{
6566 struct stream_out *out = (struct stream_out *)stream;
6567 int status = -ENOSYS;
6568 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006569 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006570 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006571 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6572 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6573 else
6574 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6575 pthread_mutex_unlock(&out->lock);
6576 }
6577 return status;
6578}
6579
6580static int out_flush(struct audio_stream_out* stream)
6581{
6582 struct stream_out *out = (struct stream_out *)stream;
6583 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006584 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006585 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006586 lock_output_stream(out);
Weiyin Jiang280ea742020-09-08 20:28:22 +08006587 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006588 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manam14c198b2020-12-24 14:08:04 +05306589 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006590 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006591 } else {
6592 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manam14c198b2020-12-24 14:08:04 +05306593 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006594 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006595 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006596 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006597 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006598 return 0;
6599 }
6600 return -ENOSYS;
6601}
6602
Haynes Mathew George16081042017-05-31 17:16:49 -07006603static int out_stop(const struct audio_stream_out* stream)
6604{
6605 struct stream_out *out = (struct stream_out *)stream;
6606 struct audio_device *adev = out->dev;
6607 int ret = -ENOSYS;
6608
6609 ALOGV("%s", __func__);
6610 pthread_mutex_lock(&adev->lock);
6611 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6612 out->playback_started && out->pcm != NULL) {
6613 pcm_stop(out->pcm);
6614 ret = stop_output_stream(out);
6615 out->playback_started = false;
6616 }
6617 pthread_mutex_unlock(&adev->lock);
6618 return ret;
6619}
6620
6621static int out_start(const struct audio_stream_out* stream)
6622{
6623 struct stream_out *out = (struct stream_out *)stream;
6624 struct audio_device *adev = out->dev;
6625 int ret = -ENOSYS;
6626
6627 ALOGV("%s", __func__);
6628 pthread_mutex_lock(&adev->lock);
6629 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6630 !out->playback_started && out->pcm != NULL) {
6631 ret = start_output_stream(out);
6632 if (ret == 0) {
6633 out->playback_started = true;
6634 }
6635 }
6636 pthread_mutex_unlock(&adev->lock);
6637 return ret;
6638}
6639
6640/*
6641 * Modify config->period_count based on min_size_frames
6642 */
6643static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6644{
6645 int periodCountRequested = (min_size_frames + config->period_size - 1)
6646 / config->period_size;
6647 int periodCount = MMAP_PERIOD_COUNT_MIN;
6648
6649 ALOGV("%s original config.period_size = %d config.period_count = %d",
6650 __func__, config->period_size, config->period_count);
6651
6652 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6653 periodCount *= 2;
6654 }
6655 config->period_count = periodCount;
6656
6657 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6658}
6659
Phil Burkfe17efd2019-03-25 10:23:35 -07006660// Read offset for the positional timestamp from a persistent vendor property.
6661// This is to workaround apparent inaccuracies in the timing information that
6662// is used by the AAudio timing model. The inaccuracies can cause glitches.
6663static int64_t get_mmap_out_time_offset() {
6664 const int32_t kDefaultOffsetMicros = 0;
6665 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006666 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006667 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6668 return mmap_time_offset_micros * (int64_t)1000;
6669}
6670
Haynes Mathew George16081042017-05-31 17:16:49 -07006671static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6672 int32_t min_size_frames,
6673 struct audio_mmap_buffer_info *info)
6674{
6675 struct stream_out *out = (struct stream_out *)stream;
6676 struct audio_device *adev = out->dev;
6677 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006678 unsigned int offset1 = 0;
6679 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006680 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006681 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006682 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006683
Arun Mirpuri5d170872019-03-26 13:21:31 -07006684 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306685 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006686 pthread_mutex_lock(&adev->lock);
6687
Sharad Sanglec6f32552018-05-04 16:15:38 +05306688 if (CARD_STATUS_OFFLINE == out->card_status ||
6689 CARD_STATUS_OFFLINE == adev->card_status) {
6690 ALOGW("out->card_status or adev->card_status offline, try again");
6691 ret = -EIO;
6692 goto exit;
6693 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306694 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006695 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6696 ret = -EINVAL;
6697 goto exit;
6698 }
6699 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6700 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6701 ret = -ENOSYS;
6702 goto exit;
6703 }
6704 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6705 if (out->pcm_device_id < 0) {
6706 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6707 __func__, out->pcm_device_id, out->usecase);
6708 ret = -EINVAL;
6709 goto exit;
6710 }
6711
6712 adjust_mmap_period_count(&out->config, min_size_frames);
6713
Arun Mirpuri5d170872019-03-26 13:21:31 -07006714 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006715 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6716 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6717 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306718 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306719 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6720 out->card_status = CARD_STATUS_OFFLINE;
6721 adev->card_status = CARD_STATUS_OFFLINE;
6722 ret = -EIO;
6723 goto exit;
6724 }
6725
Haynes Mathew George16081042017-05-31 17:16:49 -07006726 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6727 step = "open";
6728 ret = -ENODEV;
6729 goto exit;
6730 }
6731 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6732 if (ret < 0) {
6733 step = "begin";
6734 goto exit;
6735 }
juyuchen626833d2019-06-04 16:48:02 +08006736
6737 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006738 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006739 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006740 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006741 ret = platform_get_mmap_data_fd(adev->platform,
6742 out->pcm_device_id, 0 /*playback*/,
6743 &info->shared_memory_fd,
6744 &mmap_size);
6745 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006746 // Fall back to non exclusive mode
6747 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6748 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006749 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6750 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6751
Arun Mirpuri5d170872019-03-26 13:21:31 -07006752 if (mmap_size < buffer_size) {
6753 step = "mmap";
6754 goto exit;
6755 }
juyuchen626833d2019-06-04 16:48:02 +08006756 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006757 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006758 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006759 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006760
6761 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6762 if (ret < 0) {
6763 step = "commit";
6764 goto exit;
6765 }
6766
Phil Burkfe17efd2019-03-25 10:23:35 -07006767 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6768
Haynes Mathew George16081042017-05-31 17:16:49 -07006769 out->standby = false;
6770 ret = 0;
6771
Arun Mirpuri5d170872019-03-26 13:21:31 -07006772 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006773 __func__, info->shared_memory_address, info->buffer_size_frames);
6774
6775exit:
6776 if (ret != 0) {
6777 if (out->pcm == NULL) {
6778 ALOGE("%s: %s - %d", __func__, step, ret);
6779 } else {
6780 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6781 pcm_close(out->pcm);
6782 out->pcm = NULL;
6783 }
6784 }
6785 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306786 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006787 return ret;
6788}
6789
6790static int out_get_mmap_position(const struct audio_stream_out *stream,
6791 struct audio_mmap_position *position)
6792{
6793 struct stream_out *out = (struct stream_out *)stream;
6794 ALOGVV("%s", __func__);
6795 if (position == NULL) {
6796 return -EINVAL;
6797 }
6798 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006799 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006800 return -ENOSYS;
6801 }
6802 if (out->pcm == NULL) {
6803 return -ENOSYS;
6804 }
6805
6806 struct timespec ts = { 0, 0 };
6807 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6808 if (ret < 0) {
6809 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6810 return ret;
6811 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006812 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6813 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006814 return 0;
6815}
6816
6817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006818/** audio_stream_in implementation **/
6819static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6820{
6821 struct stream_in *in = (struct stream_in *)stream;
6822
6823 return in->config.rate;
6824}
6825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006826static int in_set_sample_rate(struct audio_stream *stream __unused,
6827 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006828{
6829 return -ENOSYS;
6830}
6831
6832static size_t in_get_buffer_size(const struct audio_stream *stream)
6833{
6834 struct stream_in *in = (struct stream_in *)stream;
6835
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006836 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6837 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006838 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6839 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306840 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306841 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006842
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006843 return in->config.period_size * in->af_period_multiplier *
6844 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006845}
6846
6847static uint32_t in_get_channels(const struct audio_stream *stream)
6848{
6849 struct stream_in *in = (struct stream_in *)stream;
6850
6851 return in->channel_mask;
6852}
6853
6854static audio_format_t in_get_format(const struct audio_stream *stream)
6855{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006856 struct stream_in *in = (struct stream_in *)stream;
6857
6858 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006859}
6860
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006861static int in_set_format(struct audio_stream *stream __unused,
6862 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006863{
6864 return -ENOSYS;
6865}
6866
6867static int in_standby(struct audio_stream *stream)
6868{
6869 struct stream_in *in = (struct stream_in *)stream;
6870 struct audio_device *adev = in->dev;
6871 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306872 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6873 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006874 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306875
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006876 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006877 if (!in->standby && in->is_st_session) {
6878 ALOGD("%s: sound trigger pcm stop lab", __func__);
6879 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006880 if (adev->num_va_sessions > 0)
6881 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006882 in->standby = 1;
6883 }
6884
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006885 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006886 if (adev->adm_deregister_stream)
6887 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6888
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006889 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006890 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006891 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006892 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006893 voice_extn_compress_voip_close_input_stream(stream);
6894 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006895 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6896 do_stop = in->capture_started;
6897 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006898 if (in->mmap_shared_memory_fd >= 0) {
6899 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6900 __func__, in->mmap_shared_memory_fd);
6901 close(in->mmap_shared_memory_fd);
6902 in->mmap_shared_memory_fd = -1;
6903 }
Zhou Songa8895042016-07-05 17:54:22 +08006904 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306905 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306906 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006907 }
6908
Arun Mirpuri5d170872019-03-26 13:21:31 -07006909 if (in->pcm) {
6910 ATRACE_BEGIN("pcm_in_close");
6911 pcm_close(in->pcm);
6912 ATRACE_END();
6913 in->pcm = NULL;
6914 }
6915
Carter Hsu2e429db2019-05-14 18:50:52 +08006916 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006917 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006918
George Gao3018ede2019-10-23 13:23:00 -07006919 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6920 if (adev->num_va_sessions > 0)
6921 adev->num_va_sessions--;
6922 }
Quinn Malef6050362019-01-30 15:55:40 -08006923
Eric Laurent150dbfe2013-02-27 14:31:02 -08006924 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006925 }
6926 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006927 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006928 return status;
6929}
6930
Aalique Grahame22e49102018-12-18 14:23:57 -08006931static int in_dump(const struct audio_stream *stream,
6932 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006933{
Aalique Grahame22e49102018-12-18 14:23:57 -08006934 struct stream_in *in = (struct stream_in *)stream;
6935
6936 // We try to get the lock for consistency,
6937 // but it isn't necessary for these variables.
6938 // If we're not in standby, we may be blocked on a read.
6939 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6940 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6941 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6942 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6943
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006944 char buffer[256]; // for statistics formatting
6945 if (in->start_latency_ms.n > 0) {
6946 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6947 dprintf(fd, " Start latency ms: %s\n", buffer);
6948 }
6949
Aalique Grahame22e49102018-12-18 14:23:57 -08006950 if (locked) {
6951 pthread_mutex_unlock(&in->lock);
6952 }
6953
6954 // dump error info
6955 (void)error_log_dump(
6956 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006958 return 0;
6959}
6960
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306961static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6962{
6963 if (!stream || !parms)
6964 return;
6965
6966 struct stream_in *in = (struct stream_in *)stream;
6967 struct audio_device *adev = in->dev;
6968
6969 card_status_t status;
6970 int card;
6971 if (parse_snd_card_status(parms, &card, &status) < 0)
6972 return;
6973
6974 pthread_mutex_lock(&adev->lock);
6975 bool valid_cb = (card == adev->snd_card);
6976 pthread_mutex_unlock(&adev->lock);
6977
6978 if (!valid_cb)
6979 return;
6980
6981 lock_input_stream(in);
6982 if (in->card_status != status)
6983 in->card_status = status;
6984 pthread_mutex_unlock(&in->lock);
6985
6986 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6987 use_case_table[in->usecase],
6988 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6989
6990 // a better solution would be to report error back to AF and let
6991 // it put the stream to standby
6992 if (status == CARD_STATUS_OFFLINE)
6993 in_standby(&in->stream.common);
6994
6995 return;
6996}
6997
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006998int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006999 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007000 audio_source_t source)
7001{
7002 struct audio_device *adev = in->dev;
7003 int ret = 0;
7004
7005 lock_input_stream(in);
7006 pthread_mutex_lock(&adev->lock);
7007
7008 /* no audio source uses val == 0 */
7009 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
7010 in->source = source;
7011 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
7012 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
7013 (voice_extn_compress_voip_is_format_supported(in->format)) &&
7014 (in->config.rate == 8000 || in->config.rate == 16000 ||
7015 in->config.rate == 32000 || in->config.rate == 48000 ) &&
7016 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
7017 ret = voice_extn_compress_voip_open_input_stream(in);
7018 if (ret != 0) {
7019 ALOGE("%s: Compress voip input cannot be opened, error:%d",
7020 __func__, ret);
7021 }
7022 }
7023 }
7024
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007025 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
7026 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007027 // Workaround: If routing to an non existing usb device, fail gracefully
7028 // The routing request will otherwise block during 10 second
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007029 struct str_parms *usb_addr =
7030 str_parms_create_str(get_usb_device_address(devices));
7031 if (is_usb_in_device_type(devices) && usb_addr &&
Weiyin Jiangabedea32020-12-09 12:49:19 +08007032 !audio_extn_usb_connected(NULL)) {
7033 ALOGW("%s: ignoring rerouting to non existing USB", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007034 ret = -ENOSYS;
7035 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007036 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007037 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007038 if (!in->standby && !in->is_st_session) {
7039 ALOGV("update input routing change");
7040 // inform adm before actual routing to prevent glitches.
7041 if (adev->adm_on_routing_change) {
7042 adev->adm_on_routing_change(adev->adm_data,
7043 in->capture_handle);
7044 ret = select_devices(adev, in->usecase);
7045 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7046 adev->adm_routing_changed = true;
7047 }
7048 }
7049 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007050 if (usb_addr)
7051 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007052 }
7053 pthread_mutex_unlock(&adev->lock);
7054 pthread_mutex_unlock(&in->lock);
7055
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07007056 ALOGV("%s: exit: status(%d)", __func__, ret);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07007057 return ret;
7058}
7059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007060static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
7061{
7062 struct stream_in *in = (struct stream_in *)stream;
7063 struct audio_device *adev = in->dev;
7064 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007065 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307066 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007067
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307068 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007069 parms = str_parms_create_str(kvpairs);
7070
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307071 if (!parms)
7072 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007073 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007074 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007075
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307076 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
7077 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307078 strlcpy(in->profile, value, sizeof(in->profile));
7079 ALOGV("updating stream profile with value '%s'", in->profile);
7080 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7081 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007082 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307083 in->sample_rate, in->bit_width,
7084 in->profile, &in->app_type_cfg);
7085 }
7086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007087 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007088 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089
7090 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307091error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307092 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007093}
7094
7095static char* in_get_parameters(const struct audio_stream *stream,
7096 const char *keys)
7097{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007098 struct stream_in *in = (struct stream_in *)stream;
7099 struct str_parms *query = str_parms_create_str(keys);
7100 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007101 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007102
7103 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007104 if (reply) {
7105 str_parms_destroy(reply);
7106 }
7107 if (query) {
7108 str_parms_destroy(query);
7109 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007110 ALOGE("in_get_parameters: failed to create query or reply");
7111 return NULL;
7112 }
7113
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007114 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007115
7116 voice_extn_in_get_parameters(in, query, reply);
7117
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007118 stream_get_parameter_channels(query, reply,
7119 &in->supported_channel_masks[0]);
7120 stream_get_parameter_formats(query, reply,
7121 &in->supported_formats[0]);
7122 stream_get_parameter_rates(query, reply,
7123 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007124 str = str_parms_to_str(reply);
7125 str_parms_destroy(query);
7126 str_parms_destroy(reply);
7127
7128 ALOGV("%s: exit: returns - %s", __func__, str);
7129 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007130}
7131
Aalique Grahame22e49102018-12-18 14:23:57 -08007132static int in_set_gain(struct audio_stream_in *stream,
7133 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134{
Aalique Grahame22e49102018-12-18 14:23:57 -08007135 struct stream_in *in = (struct stream_in *)stream;
7136 char mixer_ctl_name[128];
7137 struct mixer_ctl *ctl;
7138 int ctl_value;
7139
7140 ALOGV("%s: gain %f", __func__, gain);
7141
7142 if (stream == NULL)
7143 return -EINVAL;
7144
7145 /* in_set_gain() only used to silence MMAP capture for now */
7146 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7147 return -ENOSYS;
7148
7149 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7150
7151 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7152 if (!ctl) {
7153 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7154 __func__, mixer_ctl_name);
7155 return -ENOSYS;
7156 }
7157
7158 if (gain < RECORD_GAIN_MIN)
7159 gain = RECORD_GAIN_MIN;
7160 else if (gain > RECORD_GAIN_MAX)
7161 gain = RECORD_GAIN_MAX;
7162 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7163
7164 mixer_ctl_set_value(ctl, 0, ctl_value);
7165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007166 return 0;
7167}
7168
7169static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7170 size_t bytes)
7171{
7172 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307173
7174 if (in == NULL) {
7175 ALOGE("%s: stream_in ptr is NULL", __func__);
7176 return -EINVAL;
7177 }
7178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007179 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307180 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307181 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007182
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007183 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307184
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007185 if (in->is_st_session) {
7186 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7187 /* Read from sound trigger HAL */
7188 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007189 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007190 if (adev->num_va_sessions < UINT_MAX)
7191 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007192 in->standby = 0;
7193 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007194 pthread_mutex_unlock(&in->lock);
7195 return bytes;
7196 }
7197
Haynes Mathew George16081042017-05-31 17:16:49 -07007198 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7199 ret = -ENOSYS;
7200 goto exit;
7201 }
7202
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007203 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7204 !in->standby && adev->adm_routing_changed) {
7205 ret = -ENOSYS;
7206 goto exit;
7207 }
7208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007209 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007210 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7211
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007212 pthread_mutex_lock(&adev->lock);
7213 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7214 ret = voice_extn_compress_voip_start_input_stream(in);
7215 else
7216 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007217 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7218 if (adev->num_va_sessions < UINT_MAX)
7219 adev->num_va_sessions++;
7220 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007221 pthread_mutex_unlock(&adev->lock);
7222 if (ret != 0) {
7223 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 }
7225 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007226
7227 // log startup time in ms.
7228 simple_stats_log(
7229 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007231
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307232 /* Avoid read if capture_stopped is set */
7233 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7234 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7235 ret = -EINVAL;
7236 goto exit;
7237 }
7238
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007239 // what's the duration requested by the client?
7240 long ns = 0;
7241
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307242 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007243 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7244 in->config.rate;
7245
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007246 ret = request_in_focus(in, ns);
7247 if (ret != 0)
7248 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007249 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007250
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307251 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307252 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7253 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307254 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007255 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307256 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007257 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007258 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007259 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007260 } else if (audio_extn_ffv_get_stream() == in) {
7261 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307262 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007263 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307264 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7265 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7266 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7267 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307268 ret = -EINVAL;
7269 goto exit;
7270 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307271 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307272 ret = -errno;
7273 }
7274 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307275 /* bytes read is always set to bytes for non compress usecases */
7276 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007277 }
7278
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007279 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007281 /*
Quinn Malef6050362019-01-30 15:55:40 -08007282 * Instead of writing zeroes here, we could trust the hardware to always
7283 * provide zeroes when muted. This is also muted with voice recognition
7284 * usecases so that other clients do not have access to voice recognition
7285 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007286 */
Quinn Malef6050362019-01-30 15:55:40 -08007287 if ((ret == 0 && voice_get_mic_mute(adev) &&
7288 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007289 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7290 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007291 (adev->num_va_sessions &&
7292 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7293 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7294 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007295 memset(buffer, 0, bytes);
7296
7297exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307298 frame_size = audio_stream_in_frame_size(stream);
7299 if (frame_size > 0)
7300 in->frames_read += bytes_read/frame_size;
7301
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007302 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307303 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007304 pthread_mutex_unlock(&in->lock);
7305
7306 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307307 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307308 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307309 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307310 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307311 in->standby = true;
7312 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307313 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307314 bytes_read = bytes;
7315 memset(buffer, 0, bytes);
7316 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007317 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007318 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7319 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007320 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307321 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307322 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007323 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307324 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325}
7326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007327static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007328{
7329 return 0;
7330}
7331
Aalique Grahame22e49102018-12-18 14:23:57 -08007332static int in_get_capture_position(const struct audio_stream_in *stream,
7333 int64_t *frames, int64_t *time)
7334{
7335 if (stream == NULL || frames == NULL || time == NULL) {
7336 return -EINVAL;
7337 }
7338 struct stream_in *in = (struct stream_in *)stream;
7339 int ret = -ENOSYS;
7340
7341 lock_input_stream(in);
7342 // note: ST sessions do not close the alsa pcm driver synchronously
7343 // on standby. Therefore, we may return an error even though the
7344 // pcm stream is still opened.
7345 if (in->standby) {
7346 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7347 "%s stream in standby but pcm not NULL for non ST session", __func__);
7348 goto exit;
7349 }
7350 if (in->pcm) {
7351 struct timespec timestamp;
7352 unsigned int avail;
7353 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7354 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007355 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007356 - platform_capture_latency(in) * 1000LL;
Kakanaboina Ramanjaneyulu8cedb092021-03-15 15:55:29 +05307357 //Adjustment accounts for A2dp decoder latency for recording usecase
7358 // Note: decoder latency is returned in ms, while platform_capture_latency in ns.
7359 if (is_a2dp_in_device_type(&in->device_list))
7360 *time -= audio_extn_a2dp_get_decoder_latency() * 1000000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007361 ret = 0;
7362 }
7363 }
7364exit:
7365 pthread_mutex_unlock(&in->lock);
7366 return ret;
7367}
7368
Carter Hsu2e429db2019-05-14 18:50:52 +08007369static int in_update_effect_list(bool add, effect_handle_t effect,
7370 struct listnode *head)
7371{
7372 struct listnode *node;
7373 struct in_effect_list *elist = NULL;
7374 struct in_effect_list *target = NULL;
7375 int ret = 0;
7376
7377 if (!head)
7378 return ret;
7379
7380 list_for_each(node, head) {
7381 elist = node_to_item(node, struct in_effect_list, list);
7382 if (elist->handle == effect) {
7383 target = elist;
7384 break;
7385 }
7386 }
7387
7388 if (add) {
7389 if (target) {
7390 ALOGD("effect %p already exist", effect);
7391 return ret;
7392 }
7393
7394 target = (struct in_effect_list *)
7395 calloc(1, sizeof(struct in_effect_list));
7396
7397 if (!target) {
7398 ALOGE("%s:fail to allocate memory", __func__);
7399 return -ENOMEM;
7400 }
7401
7402 target->handle = effect;
7403 list_add_tail(head, &target->list);
7404 } else {
7405 if (target) {
7406 list_remove(&target->list);
7407 free(target);
7408 }
7409 }
7410
7411 return ret;
7412}
7413
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007414static int add_remove_audio_effect(const struct audio_stream *stream,
7415 effect_handle_t effect,
7416 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007417{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007418 struct stream_in *in = (struct stream_in *)stream;
7419 int status = 0;
7420 effect_descriptor_t desc;
7421
7422 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007423 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7424
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007425 if (status != 0)
7426 return status;
7427
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007428 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007429 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007430 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007431 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7432 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007433 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007434
7435 in_update_effect_list(enable, effect, &in->aec_list);
7436 enable = !list_empty(&in->aec_list);
7437 if (enable == in->enable_aec)
7438 goto exit;
7439
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007440 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007441 ALOGD("AEC enable %d", enable);
7442
Aalique Grahame22e49102018-12-18 14:23:57 -08007443 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7444 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7445 in->dev->enable_voicerx = enable;
7446 struct audio_usecase *usecase;
7447 struct listnode *node;
7448 list_for_each(node, &in->dev->usecase_list) {
7449 usecase = node_to_item(node, struct audio_usecase, list);
7450 if (usecase->type == PCM_PLAYBACK)
7451 select_devices(in->dev, usecase->id);
7452 }
7453 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007454 if (!in->standby) {
7455 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7456 select_devices(in->dev, in->usecase);
7457 }
7458
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007459 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007460 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7461
7462 in_update_effect_list(enable, effect, &in->ns_list);
7463 enable = !list_empty(&in->ns_list);
7464 if (enable == in->enable_ns)
7465 goto exit;
7466
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007467 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007468 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007469 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007470 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7471 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007472 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7473 select_devices(in->dev, in->usecase);
7474 } else
7475 select_devices(in->dev, in->usecase);
7476 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007477 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007478exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007479 pthread_mutex_unlock(&in->dev->lock);
7480 pthread_mutex_unlock(&in->lock);
7481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007482 return 0;
7483}
7484
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007485static int in_add_audio_effect(const struct audio_stream *stream,
7486 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007487{
Eric Laurent994a6932013-07-17 11:51:42 -07007488 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007489 return add_remove_audio_effect(stream, effect, true);
7490}
7491
7492static int in_remove_audio_effect(const struct audio_stream *stream,
7493 effect_handle_t effect)
7494{
Eric Laurent994a6932013-07-17 11:51:42 -07007495 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007496 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007497}
7498
Haynes Mathew George16081042017-05-31 17:16:49 -07007499static int in_stop(const struct audio_stream_in* stream)
7500{
7501 struct stream_in *in = (struct stream_in *)stream;
7502 struct audio_device *adev = in->dev;
7503
7504 int ret = -ENOSYS;
7505 ALOGV("%s", __func__);
7506 pthread_mutex_lock(&adev->lock);
7507 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7508 in->capture_started && in->pcm != NULL) {
7509 pcm_stop(in->pcm);
7510 ret = stop_input_stream(in);
7511 in->capture_started = false;
7512 }
7513 pthread_mutex_unlock(&adev->lock);
7514 return ret;
7515}
7516
7517static int in_start(const struct audio_stream_in* stream)
7518{
7519 struct stream_in *in = (struct stream_in *)stream;
7520 struct audio_device *adev = in->dev;
7521 int ret = -ENOSYS;
7522
7523 ALOGV("%s in %p", __func__, in);
7524 pthread_mutex_lock(&adev->lock);
7525 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7526 !in->capture_started && in->pcm != NULL) {
7527 if (!in->capture_started) {
7528 ret = start_input_stream(in);
7529 if (ret == 0) {
7530 in->capture_started = true;
7531 }
7532 }
7533 }
7534 pthread_mutex_unlock(&adev->lock);
7535 return ret;
7536}
7537
Phil Burke0a86d12019-02-16 22:28:11 -08007538// Read offset for the positional timestamp from a persistent vendor property.
7539// This is to workaround apparent inaccuracies in the timing information that
7540// is used by the AAudio timing model. The inaccuracies can cause glitches.
7541static int64_t in_get_mmap_time_offset() {
7542 const int32_t kDefaultOffsetMicros = 0;
7543 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007544 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007545 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7546 return mmap_time_offset_micros * (int64_t)1000;
7547}
7548
Haynes Mathew George16081042017-05-31 17:16:49 -07007549static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7550 int32_t min_size_frames,
7551 struct audio_mmap_buffer_info *info)
7552{
7553 struct stream_in *in = (struct stream_in *)stream;
7554 struct audio_device *adev = in->dev;
7555 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007556 unsigned int offset1 = 0;
7557 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007558 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007559 uint32_t mmap_size = 0;
7560 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007561
7562 pthread_mutex_lock(&adev->lock);
7563 ALOGV("%s in %p", __func__, in);
7564
Sharad Sanglec6f32552018-05-04 16:15:38 +05307565 if (CARD_STATUS_OFFLINE == in->card_status||
7566 CARD_STATUS_OFFLINE == adev->card_status) {
7567 ALOGW("in->card_status or adev->card_status offline, try again");
7568 ret = -EIO;
7569 goto exit;
7570 }
7571
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307572 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007573 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7574 ret = -EINVAL;
7575 goto exit;
7576 }
7577 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7578 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7579 ALOGV("%s in %p", __func__, in);
7580 ret = -ENOSYS;
7581 goto exit;
7582 }
7583 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7584 if (in->pcm_device_id < 0) {
7585 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7586 __func__, in->pcm_device_id, in->usecase);
7587 ret = -EINVAL;
7588 goto exit;
7589 }
7590
7591 adjust_mmap_period_count(&in->config, min_size_frames);
7592
7593 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7594 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7595 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7596 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307597 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307598 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7599 in->card_status = CARD_STATUS_OFFLINE;
7600 adev->card_status = CARD_STATUS_OFFLINE;
7601 ret = -EIO;
7602 goto exit;
7603 }
7604
Haynes Mathew George16081042017-05-31 17:16:49 -07007605 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7606 step = "open";
7607 ret = -ENODEV;
7608 goto exit;
7609 }
7610
7611 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7612 if (ret < 0) {
7613 step = "begin";
7614 goto exit;
7615 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007616
juyuchen626833d2019-06-04 16:48:02 +08007617 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007618 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7619 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7620 info->burst_size_frames = in->config.period_size;
7621 ret = platform_get_mmap_data_fd(adev->platform,
7622 in->pcm_device_id, 1 /*capture*/,
7623 &info->shared_memory_fd,
7624 &mmap_size);
7625 if (ret < 0) {
7626 // Fall back to non exclusive mode
7627 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7628 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007629 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7630 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7631
Arun Mirpuri5d170872019-03-26 13:21:31 -07007632 if (mmap_size < buffer_size) {
7633 step = "mmap";
7634 goto exit;
7635 }
juyuchen626833d2019-06-04 16:48:02 +08007636 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007637 }
7638
7639 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007640
7641 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7642 if (ret < 0) {
7643 step = "commit";
7644 goto exit;
7645 }
7646
Phil Burke0a86d12019-02-16 22:28:11 -08007647 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7648
Haynes Mathew George16081042017-05-31 17:16:49 -07007649 in->standby = false;
7650 ret = 0;
7651
7652 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7653 __func__, info->shared_memory_address, info->buffer_size_frames);
7654
7655exit:
7656 if (ret != 0) {
7657 if (in->pcm == NULL) {
7658 ALOGE("%s: %s - %d", __func__, step, ret);
7659 } else {
7660 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7661 pcm_close(in->pcm);
7662 in->pcm = NULL;
7663 }
7664 }
7665 pthread_mutex_unlock(&adev->lock);
7666 return ret;
7667}
7668
7669static int in_get_mmap_position(const struct audio_stream_in *stream,
7670 struct audio_mmap_position *position)
7671{
7672 struct stream_in *in = (struct stream_in *)stream;
7673 ALOGVV("%s", __func__);
7674 if (position == NULL) {
7675 return -EINVAL;
7676 }
Gautam Manam34d1f542021-01-05 20:24:37 +05307677 lock_input_stream(in);
Haynes Mathew George16081042017-05-31 17:16:49 -07007678 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307679 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007680 return -ENOSYS;
7681 }
7682 if (in->pcm == NULL) {
Gautam Manam34d1f542021-01-05 20:24:37 +05307683 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007684 return -ENOSYS;
7685 }
7686 struct timespec ts = { 0, 0 };
7687 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7688 if (ret < 0) {
7689 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Gautam Manam34d1f542021-01-05 20:24:37 +05307690 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007691 return ret;
7692 }
Phil Burke0a86d12019-02-16 22:28:11 -08007693 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7694 + in->mmap_time_offset_nanos;
Gautam Manam34d1f542021-01-05 20:24:37 +05307695 pthread_mutex_unlock(&in->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07007696 return 0;
7697}
7698
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307699static int in_get_active_microphones(const struct audio_stream_in *stream,
7700 struct audio_microphone_characteristic_t *mic_array,
7701 size_t *mic_count) {
7702 struct stream_in *in = (struct stream_in *)stream;
7703 struct audio_device *adev = in->dev;
7704 ALOGVV("%s", __func__);
7705
7706 lock_input_stream(in);
7707 pthread_mutex_lock(&adev->lock);
7708 int ret = platform_get_active_microphones(adev->platform,
7709 audio_channel_count_from_in_mask(in->channel_mask),
7710 in->usecase, mic_array, mic_count);
7711 pthread_mutex_unlock(&adev->lock);
7712 pthread_mutex_unlock(&in->lock);
7713
7714 return ret;
7715}
7716
7717static int adev_get_microphones(const struct audio_hw_device *dev,
7718 struct audio_microphone_characteristic_t *mic_array,
7719 size_t *mic_count) {
7720 struct audio_device *adev = (struct audio_device *)dev;
7721 ALOGVV("%s", __func__);
7722
7723 pthread_mutex_lock(&adev->lock);
7724 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7725 pthread_mutex_unlock(&adev->lock);
7726
7727 return ret;
7728}
juyuchendb308c22019-01-21 11:57:17 -07007729
7730static void in_update_sink_metadata(struct audio_stream_in *stream,
7731 const struct sink_metadata *sink_metadata) {
7732
7733 if (stream == NULL
7734 || sink_metadata == NULL
7735 || sink_metadata->tracks == NULL) {
7736 return;
7737 }
7738
7739 int error = 0;
7740 struct stream_in *in = (struct stream_in *)stream;
7741 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007742 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007743 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007744
7745 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007746
7747 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007748 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007749
7750 lock_input_stream(in);
7751 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007752 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007753
Zhou Song62ea0282020-03-22 19:53:01 +08007754 is_ha_usecase = adev->ha_proxy_enable ?
7755 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7756 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7757 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007758 && adev->voice_tx_output != NULL) {
7759 /* Use the rx device from afe-proxy record to route voice call because
7760 there is no routing if tx device is on primary hal and rx device
7761 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007762 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007763
7764 if (!voice_is_call_state_active(adev)) {
7765 if (adev->mode == AUDIO_MODE_IN_CALL) {
7766 adev->current_call_output = adev->voice_tx_output;
7767 error = voice_start_call(adev);
7768 if (error != 0)
7769 ALOGE("%s: start voice call failed %d", __func__, error);
7770 }
7771 } else {
7772 adev->current_call_output = adev->voice_tx_output;
7773 voice_update_devices_for_all_voice_usecases(adev);
7774 }
7775 }
7776
7777 pthread_mutex_unlock(&adev->lock);
7778 pthread_mutex_unlock(&in->lock);
7779}
7780
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307781int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007782 audio_io_handle_t handle,
7783 audio_devices_t devices,
7784 audio_output_flags_t flags,
7785 struct audio_config *config,
7786 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007787 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007788{
7789 struct audio_device *adev = (struct audio_device *)dev;
7790 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307791 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007792 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007793 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307794 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007795 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7796 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7797 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7798 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007799 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007800 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7801 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007802 bool force_haptic_path =
7803 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007804 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007805#ifdef AUDIO_GKI_ENABLED
7806 __s32 *generic_dec;
7807#endif
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007808 pthread_mutexattr_t latch_attr;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007809
kunleizdff872d2018-08-20 14:40:33 +08007810 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007811 is_usb_dev = false;
7812 devices = AUDIO_DEVICE_OUT_SPEAKER;
7813 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7814 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007815 if (config->format == AUDIO_FORMAT_DEFAULT)
7816 config->format = AUDIO_FORMAT_PCM_16_BIT;
7817 if (config->sample_rate == 0)
7818 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7819 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7820 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007821 }
7822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007823 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007825 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7826
Mingming Yin3a941d42016-02-17 18:08:05 -08007827 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007828 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7829 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307830
7831
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007832 if (!out) {
7833 return -ENOMEM;
7834 }
7835
Haynes Mathew George204045b2015-02-25 20:32:03 -08007836 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007837 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiang906db3c2021-03-02 13:17:04 +08007838 pthread_mutexattr_init(&latch_attr);
7839 pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
7840 pthread_mutex_init(&out->latch_lock, &latch_attr);
7841 pthread_mutexattr_destroy(&latch_attr);
Zhou Song48453a02018-01-10 17:50:59 +08007842 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007843 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007845 if (devices == AUDIO_DEVICE_NONE)
7846 devices = AUDIO_DEVICE_OUT_SPEAKER;
7847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007848 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007849 list_init(&out->device_list);
7850 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007851 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007852 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007853 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307854 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307855 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7856 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7857 else
7858 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007859 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007860 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007861 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307862 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307863 out->started = 0;
Zhou Songbaddf9f2020-11-20 13:57:39 +08007864 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007865 out->hal_output_suspend_supported = 0;
7866 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307867 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307868 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307869 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007870 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007871
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307872 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307873 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007874 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7875
Aalique Grahame22e49102018-12-18 14:23:57 -08007876 if (direct_dev &&
7877 (audio_is_linear_pcm(out->format) ||
7878 config->format == AUDIO_FORMAT_DEFAULT) &&
7879 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7880 audio_format_t req_format = config->format;
7881 audio_channel_mask_t req_channel_mask = config->channel_mask;
7882 uint32_t req_sample_rate = config->sample_rate;
7883
7884 pthread_mutex_lock(&adev->lock);
7885 if (is_hdmi) {
7886 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7887 ret = read_hdmi_sink_caps(out);
7888 if (config->sample_rate == 0)
7889 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7890 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7891 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7892 if (config->format == AUDIO_FORMAT_DEFAULT)
7893 config->format = AUDIO_FORMAT_PCM_16_BIT;
7894 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007895 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7896 &config->format,
7897 &out->supported_formats[0],
7898 MAX_SUPPORTED_FORMATS,
7899 &config->channel_mask,
7900 &out->supported_channel_masks[0],
7901 MAX_SUPPORTED_CHANNEL_MASKS,
7902 &config->sample_rate,
7903 &out->supported_sample_rates[0],
7904 MAX_SUPPORTED_SAMPLE_RATES);
7905 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007906 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007907
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007908 pthread_mutex_unlock(&adev->lock);
7909 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007910 if (ret == -ENOSYS) {
7911 /* ignore and go with default */
7912 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007913 }
7914 // For MMAP NO IRQ, allow conversions in ADSP
7915 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7916 goto error_open;
7917 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007918 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007919 goto error_open;
7920 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007921
7922 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7923 config->sample_rate = req_sample_rate;
7924 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7925 config->channel_mask = req_channel_mask;
7926 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7927 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007928 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007929
7930 out->sample_rate = config->sample_rate;
7931 out->channel_mask = config->channel_mask;
7932 out->format = config->format;
7933 if (is_hdmi) {
7934 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7935 out->config = pcm_config_hdmi_multi;
7936 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7937 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7938 out->config = pcm_config_mmap_playback;
7939 out->stream.start = out_start;
7940 out->stream.stop = out_stop;
7941 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7942 out->stream.get_mmap_position = out_get_mmap_position;
7943 } else {
7944 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7945 out->config = pcm_config_hifi;
7946 }
7947
7948 out->config.rate = out->sample_rate;
7949 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7950 if (is_hdmi) {
7951 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7952 audio_bytes_per_sample(out->format));
7953 }
7954 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007955 }
7956
Derek Chenf6318be2017-06-12 17:16:24 -04007957 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007958 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007959 /* extract car audio stream index */
7960 out->car_audio_stream =
7961 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7962 if (out->car_audio_stream < 0) {
7963 ALOGE("%s: invalid car audio stream %x",
7964 __func__, out->car_audio_stream);
7965 ret = -EINVAL;
7966 goto error_open;
7967 }
Derek Chen5f67a942020-02-24 23:08:13 -08007968 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007969 }
7970
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007971 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007972 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007973 if (!voice_extn_is_compress_voip_supported()) {
7974 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7975 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007976 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307977 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007978 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7979 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007980 out->volume_l = INVALID_OUT_VOLUME;
7981 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007982
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007983 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007984 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007985 uint32_t channel_count =
7986 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh968858a2020-08-06 16:30:48 +05307987 out->config.channels = channel_count;
7988
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007989 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7990 out->sample_rate, out->format,
7991 channel_count, false);
7992 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7993 if (frame_size != 0)
7994 out->config.period_size = buffer_size / frame_size;
7995 else
7996 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007997 }
7998 } else {
7999 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8000 voice_extn_compress_voip_is_active(out->dev)) &&
8001 (voice_extn_compress_voip_is_config_supported(config))) {
8002 ret = voice_extn_compress_voip_open_output_stream(out);
8003 if (ret != 0) {
8004 ALOGE("%s: Compress voip output cannot be opened, error:%d",
8005 __func__, ret);
8006 goto error_open;
8007 }
Sujin Panicker19027262019-09-16 18:28:06 +05308008 } else {
8009 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8010 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008011 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008012 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008013 } else if (audio_is_linear_pcm(out->format) &&
8014 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
8015 out->channel_mask = config->channel_mask;
8016 out->sample_rate = config->sample_rate;
8017 out->format = config->format;
8018 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
8019 // does this change?
8020 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
8021 out->config.rate = config->sample_rate;
8022 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
8023 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
8024 audio_bytes_per_sample(config->format));
8025 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07008026 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308027 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308028 pthread_mutex_lock(&adev->lock);
8029 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
8030 pthread_mutex_unlock(&adev->lock);
8031
8032 // reject offload during card offline to allow
8033 // fallback to s/w paths
8034 if (offline) {
8035 ret = -ENODEV;
8036 goto error_open;
8037 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008038
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008039 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
8040 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
8041 ALOGE("%s: Unsupported Offload information", __func__);
8042 ret = -EINVAL;
8043 goto error_open;
8044 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008045
Atul Khare3fa6e542017-08-09 00:56:17 +05308046 if (config->offload_info.format == 0)
8047 config->offload_info.format = config->format;
8048 if (config->offload_info.sample_rate == 0)
8049 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008050
Mingming Yin90310102013-11-13 16:57:00 -08008051 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308052 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008053 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054 ret = -EINVAL;
8055 goto error_open;
8056 }
8057
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008058 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8059 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8060 (audio_extn_passthru_is_passthrough_stream(out)) &&
8061 !((config->sample_rate == 48000) ||
8062 (config->sample_rate == 96000) ||
8063 (config->sample_rate == 192000))) {
8064 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8065 __func__, config->sample_rate, config->offload_info.format);
8066 ret = -EINVAL;
8067 goto error_open;
8068 }
8069
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008070 out->compr_config.codec = (struct snd_codec *)
8071 calloc(1, sizeof(struct snd_codec));
8072
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008073 if (!out->compr_config.codec) {
8074 ret = -ENOMEM;
8075 goto error_open;
8076 }
8077
Dhananjay Kumarac341582017-02-23 23:42:25 +05308078 out->stream.pause = out_pause;
8079 out->stream.resume = out_resume;
8080 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308081 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308082 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008083 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308084 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008085 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308086 } else {
8087 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8088 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008089 }
vivek mehta446c3962015-09-14 10:57:35 -07008090
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308091 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8092 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008093#ifdef AUDIO_GKI_ENABLED
8094 /* out->compr_config.codec->reserved[1] is for flags */
8095 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8096#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308097 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008098#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308099 }
8100
vivek mehta446c3962015-09-14 10:57:35 -07008101 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008102 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008103 config->format == 0 && config->sample_rate == 0 &&
8104 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008105 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008106 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8107 } else {
8108 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8109 ret = -EEXIST;
8110 goto error_open;
8111 }
vivek mehta446c3962015-09-14 10:57:35 -07008112 }
8113
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008114 if (config->offload_info.channel_mask)
8115 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008116 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008117 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008118 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008119 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308120 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008121 ret = -EINVAL;
8122 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008123 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008124
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008125 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008126 out->sample_rate = config->offload_info.sample_rate;
8127
Mingming Yin3ee55c62014-08-04 14:23:35 -07008128 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008129
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308130 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308131 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308132 audio_extn_dolby_send_ddp_endp_params(adev);
8133 audio_extn_dolby_set_dmid(adev);
8134 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008136 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008137 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008138 out->compr_config.codec->bit_rate =
8139 config->offload_info.bit_rate;
8140 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308141 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008142 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308143 /* Update bit width only for non passthrough usecases.
8144 * For passthrough usecases, the output will always be opened @16 bit
8145 */
8146 if (!audio_extn_passthru_is_passthrough_stream(out))
8147 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308148
8149 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008150#ifdef AUDIO_GKI_ENABLED
8151 /* out->compr_config.codec->reserved[1] is for flags */
8152 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8153 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8154#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308155 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8156 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008157#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308158
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008159 /*TODO: Do we need to change it for passthrough */
8160 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008161
Manish Dewangana6fc5442015-08-24 20:30:31 +05308162 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8163 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308164 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308165 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308166 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8167 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308168
8169 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8170 AUDIO_FORMAT_PCM) {
8171
8172 /*Based on platform support, configure appropriate alsa format for corresponding
8173 *hal input format.
8174 */
8175 out->compr_config.codec->format = hal_format_to_alsa(
8176 config->offload_info.format);
8177
Ashish Jain83a6cc22016-06-28 14:34:17 +05308178 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308179 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308180 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308181
Dhananjay Kumarac341582017-02-23 23:42:25 +05308182 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308183 *hal input format and alsa format might differ based on platform support.
8184 */
8185 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308186 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308187
8188 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8189
Deeraj Soman93155a62019-09-30 19:00:37 +05308190 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8191 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8192 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8193 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8194 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308195
Ashish Jainf1eaa582016-05-23 20:54:24 +05308196 /* Check if alsa session is configured with the same format as HAL input format,
8197 * if not then derive correct fragment size needed to accomodate the
8198 * conversion of HAL input format to alsa format.
8199 */
8200 audio_extn_utils_update_direct_pcm_fragment_size(out);
8201
8202 /*if hal input and output fragment size is different this indicates HAL input format is
8203 *not same as the alsa format
8204 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308205 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308206 /*Allocate a buffer to convert input data to the alsa configured format.
8207 *size of convert buffer is equal to the size required to hold one fragment size
8208 *worth of pcm data, this is because flinger does not write more than fragment_size
8209 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308210 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8211 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308212 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8213 ret = -ENOMEM;
8214 goto error_open;
8215 }
8216 }
8217 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8218 out->compr_config.fragment_size =
8219 audio_extn_passthru_get_buffer_size(&config->offload_info);
8220 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8221 } else {
8222 out->compr_config.fragment_size =
8223 platform_get_compress_offload_buffer_size(&config->offload_info);
8224 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8225 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008226
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308227 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8228 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8229 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008230 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8231#ifdef AUDIO_GKI_ENABLED
8232 generic_dec =
8233 &(out->compr_config.codec->options.generic.reserved[1]);
8234 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8235 AUDIO_OUTPUT_BIT_WIDTH;
8236#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308237 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008238#endif
8239 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008240
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308241 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8242 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8243 }
8244
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008245 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8246 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008247
Manish Dewangan69426c82017-01-30 17:35:36 +05308248 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8249 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8250 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8251 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8252 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8253 } else {
8254 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8255 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008256
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308257 memset(&out->channel_map_param, 0,
8258 sizeof(struct audio_out_channel_map_param));
8259
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008260 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308261 out->send_next_track_params = false;
8262 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008263 out->offload_state = OFFLOAD_STATE_IDLE;
8264 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008265 out->writeAt.tv_sec = 0;
8266 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008267
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008268 audio_extn_dts_create_state_notifier_node(out->usecase);
8269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008270 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8271 __func__, config->offload_info.version,
8272 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308273
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308274 /* Check if DSD audio format is supported in codec
8275 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308276 */
8277
8278 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308279 (!platform_check_codec_dsd_support(adev->platform) ||
8280 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308281 ret = -EINVAL;
8282 goto error_open;
8283 }
8284
Ashish Jain5106d362016-05-11 19:23:33 +05308285 /* Disable gapless if any of the following is true
8286 * passthrough playback
8287 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308288 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308289 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308290 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308291 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008292 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308293 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308294 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308295 check_and_set_gapless_mode(adev, false);
8296 } else
8297 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008298
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308299 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008300 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8301 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308302 if (config->format == AUDIO_FORMAT_DSD) {
8303 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008304#ifdef AUDIO_GKI_ENABLED
8305 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8306 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8307#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308308 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008309#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308310 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008311
8312 create_offload_callback_thread(out);
8313
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008314 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008315 switch (config->sample_rate) {
8316 case 0:
8317 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8318 break;
8319 case 8000:
8320 case 16000:
8321 case 48000:
8322 out->sample_rate = config->sample_rate;
8323 break;
8324 default:
8325 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8326 config->sample_rate);
8327 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8328 ret = -EINVAL;
8329 goto error_open;
8330 }
8331 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8332 switch (config->channel_mask) {
8333 case AUDIO_CHANNEL_NONE:
8334 case AUDIO_CHANNEL_OUT_STEREO:
8335 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8336 break;
8337 default:
8338 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8339 config->channel_mask);
8340 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8341 ret = -EINVAL;
8342 goto error_open;
8343 }
8344 switch (config->format) {
8345 case AUDIO_FORMAT_DEFAULT:
8346 case AUDIO_FORMAT_PCM_16_BIT:
8347 out->format = AUDIO_FORMAT_PCM_16_BIT;
8348 break;
8349 default:
8350 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8351 config->format);
8352 config->format = AUDIO_FORMAT_PCM_16_BIT;
8353 ret = -EINVAL;
8354 goto error_open;
8355 }
8356
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308357 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008358 if (ret != 0) {
8359 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008360 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008361 goto error_open;
8362 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008363 } else if (is_single_device_type_equal(&out->device_list,
8364 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008365 switch (config->sample_rate) {
8366 case 0:
8367 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8368 break;
8369 case 8000:
8370 case 16000:
8371 case 48000:
8372 out->sample_rate = config->sample_rate;
8373 break;
8374 default:
8375 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8376 config->sample_rate);
8377 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8378 ret = -EINVAL;
8379 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008380 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008381 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8382 switch (config->channel_mask) {
8383 case AUDIO_CHANNEL_NONE:
8384 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8385 break;
8386 case AUDIO_CHANNEL_OUT_STEREO:
8387 out->channel_mask = config->channel_mask;
8388 break;
8389 default:
8390 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8391 config->channel_mask);
8392 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8393 ret = -EINVAL;
8394 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008395 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008396 switch (config->format) {
8397 case AUDIO_FORMAT_DEFAULT:
8398 out->format = AUDIO_FORMAT_PCM_16_BIT;
8399 break;
8400 case AUDIO_FORMAT_PCM_16_BIT:
8401 out->format = config->format;
8402 break;
8403 default:
8404 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8405 config->format);
8406 config->format = AUDIO_FORMAT_PCM_16_BIT;
8407 ret = -EINVAL;
8408 break;
8409 }
8410 if (ret != 0)
8411 goto error_open;
8412
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008413 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8414 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008415 out->config.rate = out->sample_rate;
8416 out->config.channels =
8417 audio_channel_count_from_out_mask(out->channel_mask);
8418 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008419 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008420 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308421 unsigned int channels = 0;
8422 /*Update config params to default if not set by the caller*/
8423 if (config->sample_rate == 0)
8424 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8425 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8426 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8427 if (config->format == AUDIO_FORMAT_DEFAULT)
8428 config->format = AUDIO_FORMAT_PCM_16_BIT;
8429
8430 channels = audio_channel_count_from_out_mask(out->channel_mask);
8431
Varun Balaraje49253e2017-07-06 19:48:56 +05308432 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8433 out->usecase = get_interactive_usecase(adev);
8434 out->config = pcm_config_low_latency;
8435 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308436 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008437 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8438 out->flags);
8439 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008440 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8441 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8442 out->config = pcm_config_mmap_playback;
8443 out->stream.start = out_start;
8444 out->stream.stop = out_stop;
8445 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8446 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308447 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8448 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008449 out->hal_output_suspend_supported =
8450 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8451 out->dynamic_pm_qos_config_supported =
8452 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8453 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008454 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8455 } else {
8456 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8457 //the mixer path will be a string similar to "low-latency-playback resume"
8458 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8459 strlcat(out->pm_qos_mixer_path,
8460 " resume", MAX_MIXER_PATH_LEN);
8461 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8462 out->pm_qos_mixer_path);
8463 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308464 out->config = pcm_config_low_latency;
8465 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8466 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8467 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308468 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8469 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8470 if (out->config.period_size <= 0) {
8471 ALOGE("Invalid configuration period size is not valid");
8472 ret = -EINVAL;
8473 goto error_open;
8474 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008475 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8476 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8477 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008478 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8479 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8480 out->config = pcm_config_haptics_audio;
8481 if (force_haptic_path)
8482 adev->haptics_config = pcm_config_haptics_audio;
8483 else
8484 adev->haptics_config = pcm_config_haptics;
8485
Meng Wangd08ce322020-04-02 08:59:20 +08008486 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008487 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8488
8489 if (force_haptic_path) {
8490 out->config.channels = 1;
8491 adev->haptics_config.channels = 1;
8492 } else
8493 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 -08008494 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008495 ret = audio_extn_auto_hal_open_output_stream(out);
8496 if (ret) {
8497 ALOGE("%s: Failed to open output stream for bus device", __func__);
8498 ret = -EINVAL;
8499 goto error_open;
8500 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308501 } else {
8502 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008503 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8504 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308505 }
8506 out->hal_ip_format = format = out->format;
8507 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8508 out->hal_op_format = pcm_format_to_hal(out->config.format);
8509 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8510 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008511 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308512 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308513 if (out->hal_ip_format != out->hal_op_format) {
8514 uint32_t buffer_size = out->config.period_size *
8515 format_to_bitwidth_table[out->hal_op_format] *
8516 out->config.channels;
8517 out->convert_buffer = calloc(1, buffer_size);
8518 if (out->convert_buffer == NULL){
8519 ALOGE("Allocation failed for convert buffer for size %d",
8520 out->compr_config.fragment_size);
8521 ret = -ENOMEM;
8522 goto error_open;
8523 }
8524 ALOGD("Convert buffer allocated of size %d", buffer_size);
8525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008526 }
8527
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008528 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8529 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308530
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008531 /* TODO remove this hardcoding and check why width is zero*/
8532 if (out->bit_width == 0)
8533 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308534 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008535 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008536 &out->device_list, out->flags,
8537 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308538 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308539 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008540 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008541 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8542 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008543 if(adev->primary_output == NULL)
8544 adev->primary_output = out;
8545 else {
8546 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008547 ret = -EEXIST;
8548 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008549 }
8550 }
8551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552 /* Check if this usecase is already existing */
8553 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008554 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8555 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008556 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008557 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008558 ret = -EEXIST;
8559 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008560 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008562 pthread_mutex_unlock(&adev->lock);
8563
8564 out->stream.common.get_sample_rate = out_get_sample_rate;
8565 out->stream.common.set_sample_rate = out_set_sample_rate;
8566 out->stream.common.get_buffer_size = out_get_buffer_size;
8567 out->stream.common.get_channels = out_get_channels;
8568 out->stream.common.get_format = out_get_format;
8569 out->stream.common.set_format = out_set_format;
8570 out->stream.common.standby = out_standby;
8571 out->stream.common.dump = out_dump;
8572 out->stream.common.set_parameters = out_set_parameters;
8573 out->stream.common.get_parameters = out_get_parameters;
8574 out->stream.common.add_audio_effect = out_add_audio_effect;
8575 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8576 out->stream.get_latency = out_get_latency;
8577 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008578#ifdef NO_AUDIO_OUT
8579 out->stream.write = out_write_for_no_output;
8580#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008581 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008582#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008583 out->stream.get_render_position = out_get_render_position;
8584 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008585 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008586
Haynes Mathew George16081042017-05-31 17:16:49 -07008587 if (out->realtime)
8588 out->af_period_multiplier = af_period_multiplier;
8589 else
8590 out->af_period_multiplier = 1;
8591
Andy Hunga1f48fa2019-07-01 18:14:53 -07008592 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008594 out->standby = 1;
Zhou Songbaddf9f2020-11-20 13:57:39 +08008595 out->volume_l = PLAYBACK_GAIN_MAX;
8596 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008597 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008598 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008599
8600 config->format = out->stream.common.get_format(&out->stream.common);
8601 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8602 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308603 register_format(out->format, out->supported_formats);
8604 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8605 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008606
Aalique Grahame22e49102018-12-18 14:23:57 -08008607 out->error_log = error_log_create(
8608 ERROR_LOG_ENTRIES,
8609 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8610
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308611 /*
8612 By locking output stream before registering, we allow the callback
8613 to update stream's state only after stream's initial state is set to
8614 adev state.
8615 */
8616 lock_output_stream(out);
8617 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8618 pthread_mutex_lock(&adev->lock);
8619 out->card_status = adev->card_status;
8620 pthread_mutex_unlock(&adev->lock);
8621 pthread_mutex_unlock(&out->lock);
8622
Aalique Grahame22e49102018-12-18 14:23:57 -08008623 stream_app_type_cfg_init(&out->app_type_cfg);
8624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008625 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308626 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008627 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008628
8629 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8630 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8631 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008632 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308633 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008634 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008635 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308636 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8637 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008638 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8639 out->usecase, PCM_PLAYBACK);
8640 hdlr_stream_cfg.flags = out->flags;
8641 hdlr_stream_cfg.type = PCM_PLAYBACK;
8642 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8643 &hdlr_stream_cfg);
8644 if (ret) {
8645 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8646 out->adsp_hdlr_stream_handle = NULL;
8647 }
8648 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308649 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8650 is_direct_passthough, false);
8651 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8652 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008653 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008654 if (ret < 0) {
8655 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8656 out->ip_hdlr_handle = NULL;
8657 }
8658 }
Derek Chenf939fb72018-11-13 13:34:41 -08008659
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008660 ret = io_streams_map_insert(adev, &out->stream.common,
8661 out->handle, AUDIO_PATCH_HANDLE_NONE);
8662 if (ret != 0)
8663 goto error_open;
8664
Susan Wang6dd13092021-01-25 10:27:11 -05008665 out->out_ctxt.output = out;
Derek Chenf939fb72018-11-13 13:34:41 -08008666
8667 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05008668 list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08008669 pthread_mutex_unlock(&adev->lock);
8670
Eric Laurent994a6932013-07-17 11:51:42 -07008671 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008672 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008673
8674error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308675 if (out->convert_buffer)
8676 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008677 free(out);
8678 *stream_out = NULL;
8679 ALOGD("%s: exit: ret %d", __func__, ret);
8680 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008681}
8682
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308683void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008684 struct audio_stream_out *stream)
8685{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008686 struct stream_out *out = (struct stream_out *)stream;
8687 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008688 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008689
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008690 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308691
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008692 io_streams_map_remove(adev, out->handle);
8693
Susan Wang6dd13092021-01-25 10:27:11 -05008694 // remove out_ctxt early to prevent the stream
8695 // being opened in a race condition
8696 pthread_mutex_lock(&adev->lock);
8697 list_remove(&out->out_ctxt.list);
8698 pthread_mutex_unlock(&adev->lock);
8699
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308700 // must deregister from sndmonitor first to prevent races
8701 // between the callback and close_stream
8702 audio_extn_snd_mon_unregister_listener(out);
8703
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008704 /* close adsp hdrl session before standby */
8705 if (out->adsp_hdlr_stream_handle) {
8706 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8707 if (ret)
8708 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8709 out->adsp_hdlr_stream_handle = NULL;
8710 }
8711
Manish Dewangan21a850a2017-08-14 12:03:55 +05308712 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008713 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8714 out->ip_hdlr_handle = NULL;
8715 }
8716
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008717 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308718 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008719 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308720 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308721 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008722 if(ret != 0)
8723 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8724 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008725 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008726 out_standby(&stream->common);
8727
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008728 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008729 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008730 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008731 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008732 if (out->compr_config.codec != NULL)
8733 free(out->compr_config.codec);
8734 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008735
Zhou Songbaddf9f2020-11-20 13:57:39 +08008736 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308737
Varun Balaraje49253e2017-07-06 19:48:56 +05308738 if (is_interactive_usecase(out->usecase))
8739 free_interactive_usecase(adev, out->usecase);
8740
Ashish Jain83a6cc22016-06-28 14:34:17 +05308741 if (out->convert_buffer != NULL) {
8742 free(out->convert_buffer);
8743 out->convert_buffer = NULL;
8744 }
8745
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008746 if (adev->voice_tx_output == out)
8747 adev->voice_tx_output = NULL;
8748
Aalique Grahame22e49102018-12-18 14:23:57 -08008749 error_log_destroy(out->error_log);
8750 out->error_log = NULL;
8751
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308752 if (adev->primary_output == out)
8753 adev->primary_output = NULL;
8754
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008755 pthread_cond_destroy(&out->cond);
8756 pthread_mutex_destroy(&out->lock);
Weiyin Jiang280ea742020-09-08 20:28:22 +08008757 pthread_mutex_destroy(&out->pre_lock);
8758 pthread_mutex_destroy(&out->latch_lock);
8759 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008760
8761 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008763 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008764 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008765}
8766
8767static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8768{
8769 struct audio_device *adev = (struct audio_device *)dev;
8770 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008771 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008772 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008773 int ret;
8774 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008775 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008776 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008777 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008778
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008779 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008780 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008781
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308782 if (!parms)
8783 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308784
Derek Chen6f293672019-04-01 01:40:24 -07008785 /* notify adev and input/output streams on the snd card status */
8786 adev_snd_mon_cb((void *)adev, parms);
8787
Weiyin Jiang24f55292020-12-22 14:35:46 +08008788 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8789 if (ret >= 0) {
8790 list_for_each(node, &adev->active_outputs_list) {
8791 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8792 streams_output_ctxt_t,
8793 list);
8794 out_snd_mon_cb((void *)out_ctxt->output, parms);
8795 }
Derek Chen6f293672019-04-01 01:40:24 -07008796
Weiyin Jiang24f55292020-12-22 14:35:46 +08008797 list_for_each(node, &adev->active_inputs_list) {
8798 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8799 streams_input_ctxt_t,
8800 list);
8801 in_snd_mon_cb((void *)in_ctxt->input, parms);
8802 }
Derek Chen6f293672019-04-01 01:40:24 -07008803 }
8804
Zhou Songd6d71752019-05-21 18:08:51 +08008805 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308806 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8807 if (ret >= 0) {
8808 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008809 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308810 adev->bt_sco_on = true;
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308811 /*
8812 * When ever BT_SCO=ON arrives, make sure to route
8813 * all use cases to SCO device, otherwise due to delay in
8814 * BT_SCO=ON and lack of synchronization with create audio patch
8815 * request for SCO device, some times use case not routed properly to
8816 * SCO device
8817 */
8818 struct audio_usecase *usecase;
8819 struct listnode *node;
8820 list_for_each(node, &adev->usecase_list) {
8821 usecase = node_to_item(node, struct audio_usecase, list);
Mingshu Pangef517202021-04-22 10:35:00 +08008822 if (usecase->stream.in && (usecase->type == PCM_CAPTURE ||
8823 usecase->type == VOICE_CALL) &&
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308824 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device))) {
8825 ALOGD("BT_SCO ON, switch all in use case to it");
8826 select_devices(adev, usecase->id);
8827 }
Mingshu Pangef517202021-04-22 10:35:00 +08008828 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
8829 usecase->type == VOICE_CALL) &&
Shalini Manjunatha3a2e06e2021-02-01 12:23:49 +05308830 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE))) {
8831 ALOGD("BT_SCO ON, switch all out use case to it");
8832 select_devices(adev, usecase->id);
8833 }
8834 }
8835 }
8836 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308837 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008838 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008839 }
8840 }
8841
8842 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiang280ea742020-09-08 20:28:22 +08008843 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008844 if (!strncmp(value, "false", 5) &&
8845 audio_extn_a2dp_source_is_suspended()) {
8846 struct audio_usecase *usecase;
8847 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008848 list_for_each(node, &adev->usecase_list) {
8849 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008850 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008851 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008852 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008853 reassign_device_list(&usecase->stream.in->device_list,
8854 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008855 select_devices(adev, usecase->id);
8856 }
Zhou Songd6d71752019-05-21 18:08:51 +08008857 }
8858 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308859 }
8860
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008861 status = voice_set_parameters(adev, parms);
8862 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008863 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008864
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008865 status = platform_set_parameters(adev->platform, parms);
8866 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008867 goto done;
8868
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008869 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8870 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008871 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008872 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8873 adev->bluetooth_nrec = true;
8874 else
8875 adev->bluetooth_nrec = false;
8876 }
8877
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008878 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8879 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8881 adev->screen_off = false;
8882 else
8883 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008884 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885 }
8886
Eric Laurent4b084132018-10-19 17:33:43 -07008887 ret = str_parms_get_int(parms, "rotation", &val);
8888 if (ret >= 0) {
8889 bool reverse_speakers = false;
8890 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8891 switch (val) {
8892 // FIXME: note that the code below assumes that the speakers are in the correct placement
8893 // relative to the user when the device is rotated 90deg from its default rotation. This
8894 // assumption is device-specific, not platform-specific like this code.
8895 case 270:
8896 reverse_speakers = true;
8897 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8898 break;
8899 case 0:
8900 case 180:
8901 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8902 break;
8903 case 90:
8904 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8905 break;
8906 default:
8907 ALOGE("%s: unexpected rotation of %d", __func__, val);
8908 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008909 }
Eric Laurent4b084132018-10-19 17:33:43 -07008910 if (status == 0) {
8911 // check and set swap
8912 // - check if orientation changed and speaker active
8913 // - set rotation and cache the rotation value
8914 adev->camera_orientation =
8915 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8916 if (!audio_extn_is_maxx_audio_enabled())
8917 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8918 }
8919 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008920
Mingming Yin514a8bc2014-07-29 15:22:21 -07008921 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8922 if (ret >= 0) {
8923 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8924 adev->bt_wb_speech_enabled = true;
8925 else
8926 adev->bt_wb_speech_enabled = false;
8927 }
8928
Zhou Song12c29502019-03-16 10:37:18 +08008929 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8930 if (ret >= 0) {
8931 val = atoi(value);
8932 adev->swb_speech_mode = val;
8933 }
8934
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008935 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8936 if (ret >= 0) {
8937 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308938 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008939 if (audio_is_output_device(val) &&
8940 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008941 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008942 platform_get_controller_stream_from_params(parms, &controller, &stream);
8943 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8944 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008945 if (ret < 0) {
8946 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308947 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008948 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008949 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308950 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008951 /*
8952 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8953 * Per AudioPolicyManager, USB device is higher priority than WFD.
8954 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8955 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8956 * starting voice call on USB
8957 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008958 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308959 if (ret >= 0)
8960 audio_extn_usb_add_device(device, atoi(value));
8961
Zhou Song6f862822017-11-06 17:27:57 +08008962 if (!audio_extn_usb_is_tunnel_supported()) {
8963 ALOGV("detected USB connect .. disable proxy");
8964 adev->allow_afe_proxy_usage = false;
8965 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008966 }
8967 }
8968
8969 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8970 if (ret >= 0) {
8971 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308972 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008973 /*
8974 * The HDMI / Displayport disconnect handling has been moved to
8975 * audio extension to ensure that its parameters are not
8976 * invalidated prior to updating sysfs of the disconnect event
8977 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8978 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308979 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008980 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308981 if (ret >= 0)
8982 audio_extn_usb_remove_device(device, atoi(value));
8983
Zhou Song6f862822017-11-06 17:27:57 +08008984 if (!audio_extn_usb_is_tunnel_supported()) {
8985 ALOGV("detected USB disconnect .. enable proxy");
8986 adev->allow_afe_proxy_usage = true;
8987 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008988 }
8989 }
8990
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008991 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008992
8993 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008994 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308995 struct audio_usecase *usecase;
8996 struct listnode *node;
8997 list_for_each(node, &adev->usecase_list) {
8998 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008999 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
9000 continue;
9001
9002 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309003 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309004 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309005 ALOGD("Switching to speaker and muting the stream before select_devices");
9006 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309007 //force device switch to re configure encoder
9008 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05309009 ALOGD("Unmuting the stream after select_devices");
Zhou Songbaddf9f2020-11-20 13:57:39 +08009010 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309011 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309012 break;
Zhou Songd01e7a22020-09-23 22:49:01 +08009013 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009014 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +08009015 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiang280ea742020-09-08 20:28:22 +08009016 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
9017 reassign_device_list(&usecase->stream.out->device_list,
9018 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
9019 check_a2dp_restore_l(adev, usecase->stream.out, true);
9020 break;
9021 }
9022 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05309023 }
9024 }
9025 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009026
9027 //handle vr audio setparam
9028 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9029 value, sizeof(value));
9030 if (ret >= 0) {
9031 ALOGI("Setting vr mode to be %s", value);
9032 if (!strncmp(value, "true", 4)) {
9033 adev->vr_audio_mode_enabled = true;
9034 ALOGI("Setting vr mode to true");
9035 } else if (!strncmp(value, "false", 5)) {
9036 adev->vr_audio_mode_enabled = false;
9037 ALOGI("Setting vr mode to false");
9038 } else {
9039 ALOGI("wrong vr mode set");
9040 }
9041 }
9042
Eric Laurent4b084132018-10-19 17:33:43 -07009043 //FIXME: to be replaced by proper video capture properties API
9044 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
9045 if (ret >= 0) {
9046 int camera_facing = CAMERA_FACING_BACK;
9047 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
9048 camera_facing = CAMERA_FACING_FRONT;
9049 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
9050 camera_facing = CAMERA_FACING_BACK;
9051 else {
9052 ALOGW("%s: invalid camera facing value: %s", __func__, value);
9053 goto done;
9054 }
9055 adev->camera_orientation =
9056 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
9057 struct audio_usecase *usecase;
9058 struct listnode *node;
9059 list_for_each(node, &adev->usecase_list) {
9060 usecase = node_to_item(node, struct audio_usecase, list);
9061 struct stream_in *in = usecase->stream.in;
9062 if (usecase->type == PCM_CAPTURE && in != NULL &&
9063 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9064 select_devices(adev, in->usecase);
9065 }
9066 }
9067 }
9068
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309069 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009070done:
9071 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009072 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309073error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009074 ALOGV("%s: exit with code(%d)", __func__, status);
9075 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009076}
9077
9078static char* adev_get_parameters(const struct audio_hw_device *dev,
9079 const char *keys)
9080{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309081 ALOGD("%s:%s", __func__, keys);
9082
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009083 struct audio_device *adev = (struct audio_device *)dev;
9084 struct str_parms *reply = str_parms_create();
9085 struct str_parms *query = str_parms_create_str(keys);
9086 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309087 char value[256] = {0};
9088 int ret = 0;
9089
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009090 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009091 if (reply) {
9092 str_parms_destroy(reply);
9093 }
9094 if (query) {
9095 str_parms_destroy(query);
9096 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009097 ALOGE("adev_get_parameters: failed to create query or reply");
9098 return NULL;
9099 }
9100
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009101 //handle vr audio getparam
9102
9103 ret = str_parms_get_str(query,
9104 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9105 value, sizeof(value));
9106
9107 if (ret >= 0) {
9108 bool vr_audio_enabled = false;
9109 pthread_mutex_lock(&adev->lock);
9110 vr_audio_enabled = adev->vr_audio_mode_enabled;
9111 pthread_mutex_unlock(&adev->lock);
9112
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009113 ALOGV("getting vr mode to %d", vr_audio_enabled);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009114
9115 if (vr_audio_enabled) {
9116 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9117 "true");
9118 goto exit;
9119 } else {
9120 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9121 "false");
9122 goto exit;
9123 }
9124 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009125
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009126 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009127 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009128 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009129 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009130 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009131 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309132 pthread_mutex_unlock(&adev->lock);
9133
Naresh Tannirud7205b62014-06-20 02:54:48 +05309134exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009135 str = str_parms_to_str(reply);
9136 str_parms_destroy(query);
9137 str_parms_destroy(reply);
9138
Aniket Kumar Latad13758f2020-08-06 15:11:36 -07009139 ALOGV("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009140 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009141}
9142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009143static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144{
9145 return 0;
9146}
9147
9148static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9149{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009150 int ret;
9151 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009152
9153 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9154
Haynes Mathew George5191a852013-09-11 14:19:36 -07009155 pthread_mutex_lock(&adev->lock);
9156 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009157 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009158 pthread_mutex_unlock(&adev->lock);
9159 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009160}
9161
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009162static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9163 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009164{
9165 return -ENOSYS;
9166}
9167
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009168static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9169 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009170{
9171 return -ENOSYS;
9172}
9173
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009174static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9175 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176{
9177 return -ENOSYS;
9178}
9179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009180static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9181 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009182{
9183 return -ENOSYS;
9184}
9185
9186static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9187{
9188 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009189 struct listnode *node;
9190 struct audio_usecase *usecase = NULL;
9191 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009193 pthread_mutex_lock(&adev->lock);
9194 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309195 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9196 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009197 adev->mode = mode;
Weiyin Jiang96b96f72020-09-22 16:48:19 +08009198 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309199 adev->current_call_output = adev->primary_output;
9200 voice_start_call(adev);
9201 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009202 (mode == AUDIO_MODE_NORMAL ||
9203 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009204 list_for_each(node, &adev->usecase_list) {
9205 usecase = node_to_item(node, struct audio_usecase, list);
9206 if (usecase->type == VOICE_CALL)
9207 break;
9208 }
9209 if (usecase &&
9210 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9211 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9212 true);
9213 if (ret != 0) {
9214 /* default service interval was successfully updated,
9215 reopen USB backend with new service interval */
9216 check_usecases_codec_backend(adev,
9217 usecase,
9218 usecase->out_snd_device);
9219 }
9220 }
9221
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009222 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009223 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009224 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009225 // restore device for other active usecases after stop call
9226 list_for_each(node, &adev->usecase_list) {
9227 usecase = node_to_item(node, struct audio_usecase, list);
9228 select_devices(adev, usecase->id);
9229 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231 }
9232 pthread_mutex_unlock(&adev->lock);
9233 return 0;
9234}
9235
9236static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9237{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009238 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009239 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009240
9241 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009242 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009243 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009244
Derek Chend2530072014-11-24 12:39:14 -08009245 if (adev->ext_hw_plugin)
9246 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009247
9248 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009249 pthread_mutex_unlock(&adev->lock);
9250
9251 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009252}
9253
9254static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9255{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009256 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009257 return 0;
9258}
9259
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009260static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009261 const struct audio_config *config)
9262{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009263 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009264
Aalique Grahame22e49102018-12-18 14:23:57 -08009265 /* Don't know if USB HIFI in this context so use true to be conservative */
9266 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9267 true /*is_usb_hifi */) != 0)
9268 return 0;
9269
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009270 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9271 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009272}
9273
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009274static bool adev_input_allow_hifi_record(struct audio_device *adev,
9275 audio_devices_t devices,
9276 audio_input_flags_t flags,
9277 audio_source_t source) {
9278 const bool allowed = true;
9279
9280 if (!audio_is_usb_in_device(devices))
9281 return !allowed;
9282
9283 switch (flags) {
9284 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009285 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009286 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9287 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009288 default:
9289 return !allowed;
9290 }
9291
9292 switch (source) {
9293 case AUDIO_SOURCE_DEFAULT:
9294 case AUDIO_SOURCE_MIC:
9295 case AUDIO_SOURCE_UNPROCESSED:
9296 break;
9297 default:
9298 return !allowed;
9299 }
9300
9301 switch (adev->mode) {
9302 case 0:
9303 break;
9304 default:
9305 return !allowed;
9306 }
9307
9308 return allowed;
9309}
9310
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009311static int adev_update_voice_comm_input_stream(struct stream_in *in,
9312 struct audio_config *config)
9313{
9314 bool valid_rate = (config->sample_rate == 8000 ||
9315 config->sample_rate == 16000 ||
9316 config->sample_rate == 32000 ||
9317 config->sample_rate == 48000);
9318 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9319
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009320 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009321 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009322 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9323 in->config = default_pcm_config_voip_copp;
9324 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9325 DEFAULT_VOIP_BUF_DURATION_MS,
9326 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009327 } else {
9328 ALOGW("%s No valid input in voip, use defaults"
9329 "sample rate %u, channel mask 0x%X",
9330 __func__, config->sample_rate, in->channel_mask);
9331 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009332 in->config.rate = config->sample_rate;
9333 in->sample_rate = config->sample_rate;
9334 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009335 //XXX needed for voice_extn_compress_voip_open_input_stream
9336 in->config.rate = config->sample_rate;
9337 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309338 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009339 voice_extn_compress_voip_is_active(in->dev)) &&
9340 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9341 valid_rate && valid_ch) {
9342 voice_extn_compress_voip_open_input_stream(in);
9343 // update rate entries to match config from AF
9344 in->config.rate = config->sample_rate;
9345 in->sample_rate = config->sample_rate;
9346 } else {
9347 ALOGW("%s compress voip not active, use defaults", __func__);
9348 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009349 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009350 return 0;
9351}
9352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009353static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009354 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009355 audio_devices_t devices,
9356 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009357 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309358 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009359 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009360 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009361{
9362 struct audio_device *adev = (struct audio_device *)dev;
9363 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009364 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009365 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009366 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309367 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009368 bool is_usb_dev = audio_is_usb_in_device(devices);
9369 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9370 devices,
9371 flags,
9372 source);
Andy Hung94320602018-10-29 18:31:12 -07009373 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9374 " sample_rate %u, channel_mask %#x, format %#x",
9375 __func__, flags, is_usb_dev, may_use_hifi_record,
9376 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309377
kunleizdff872d2018-08-20 14:40:33 +08009378 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009379 is_usb_dev = false;
9380 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9381 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9382 __func__, devices);
9383 }
9384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009385 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009386
9387 if (!(is_usb_dev && may_use_hifi_record)) {
9388 if (config->sample_rate == 0)
9389 config->sample_rate = 48000;
9390 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9391 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9392 if (config->format == AUDIO_FORMAT_DEFAULT)
9393 config->format = AUDIO_FORMAT_PCM_16_BIT;
9394
9395 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9396
Aalique Grahame22e49102018-12-18 14:23:57 -08009397 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9398 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009399 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309400 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009401
9402 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009403
9404 if (!in) {
9405 ALOGE("failed to allocate input stream");
9406 return -ENOMEM;
9407 }
9408
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309409 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309410 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9411 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009412 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009413 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009415 in->stream.common.get_sample_rate = in_get_sample_rate;
9416 in->stream.common.set_sample_rate = in_set_sample_rate;
9417 in->stream.common.get_buffer_size = in_get_buffer_size;
9418 in->stream.common.get_channels = in_get_channels;
9419 in->stream.common.get_format = in_get_format;
9420 in->stream.common.set_format = in_set_format;
9421 in->stream.common.standby = in_standby;
9422 in->stream.common.dump = in_dump;
9423 in->stream.common.set_parameters = in_set_parameters;
9424 in->stream.common.get_parameters = in_get_parameters;
9425 in->stream.common.add_audio_effect = in_add_audio_effect;
9426 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9427 in->stream.set_gain = in_set_gain;
9428 in->stream.read = in_read;
9429 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009430 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309431 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009432 in->stream.set_microphone_direction = in_set_microphone_direction;
9433 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009434 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009435
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009436 list_init(&in->device_list);
9437 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009438 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009439 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009440 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009441 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009442 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009443 in->bit_width = 16;
9444 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009445 in->direction = MIC_DIRECTION_UNSPECIFIED;
9446 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009447 list_init(&in->aec_list);
9448 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009449 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009450
Andy Hung94320602018-10-29 18:31:12 -07009451 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009452 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9453 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9454 /* Force channel config requested to mono if incall
9455 record is being requested for only uplink/downlink */
9456 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9457 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9458 ret = -EINVAL;
9459 goto err_open;
9460 }
9461 }
9462
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009463 if (is_usb_dev && may_use_hifi_record) {
9464 /* HiFi record selects an appropriate format, channel, rate combo
9465 depending on sink capabilities*/
9466 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9467 &config->format,
9468 &in->supported_formats[0],
9469 MAX_SUPPORTED_FORMATS,
9470 &config->channel_mask,
9471 &in->supported_channel_masks[0],
9472 MAX_SUPPORTED_CHANNEL_MASKS,
9473 &config->sample_rate,
9474 &in->supported_sample_rates[0],
9475 MAX_SUPPORTED_SAMPLE_RATES);
9476 if (ret != 0) {
9477 ret = -EINVAL;
9478 goto err_open;
9479 }
9480 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009481 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309482 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309483 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9484 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9485 in->config.format = PCM_FORMAT_S32_LE;
9486 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309487 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9488 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9489 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9490 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9491 bool ret_error = false;
9492 in->bit_width = 24;
9493 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9494 from HAL is 24_packed and 8_24
9495 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9496 24_packed return error indicating supported format is 24_packed
9497 *> In case of any other source requesting 24 bit or float return error
9498 indicating format supported is 16 bit only.
9499
9500 on error flinger will retry with supported format passed
9501 */
9502 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9503 (source != AUDIO_SOURCE_CAMCORDER)) {
9504 config->format = AUDIO_FORMAT_PCM_16_BIT;
9505 if (config->sample_rate > 48000)
9506 config->sample_rate = 48000;
9507 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009508 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9509 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309510 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9511 ret_error = true;
9512 }
9513
9514 if (ret_error) {
9515 ret = -EINVAL;
9516 goto err_open;
9517 }
9518 }
9519
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009520 in->channel_mask = config->channel_mask;
9521 in->format = config->format;
9522
9523 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309524
Huicheng Liu1404ba12020-09-11 01:03:25 -04009525 /* validate bus device address */
9526 if (compare_device_type(&in->device_list, AUDIO_DEVICE_IN_BUS)) {
9527 /* extract car audio stream index */
9528 in->car_audio_stream =
9529 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
9530 if (in->car_audio_stream < 0) {
9531 ALOGE("%s: invalid car audio stream %x",
9532 __func__, in->car_audio_stream);
9533 ret = -EINVAL;
9534 goto err_open;
9535 }
9536 ALOGV("%s: car_audio_stream 0x%x", __func__, in->car_audio_stream);
Huicheng Liuea4fd422021-01-12 18:34:50 -05009537 ret = audio_extn_auto_hal_open_input_stream(in);
9538 if (ret) {
9539 ALOGE("%s: Failed to open input stream for bus device", __func__);
9540 ret = -EINVAL;
9541 goto err_open;
9542 }
Huicheng Liu1404ba12020-09-11 01:03:25 -04009543 }
9544
Susan Wange3959562021-03-11 11:50:26 -05009545 /* reassign use case for echo reference stream on automotive platforms */
9546 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
9547 ret = audio_extn_auto_hal_open_echo_reference_stream(in);
9548 }
9549
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309550 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9551 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9552 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9553 else {
9554 ret = -EINVAL;
9555 goto err_open;
9556 }
9557 }
9558
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009559 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309560 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9561 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009562 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9563 is_low_latency = true;
9564#if LOW_LATENCY_CAPTURE_USE_CASE
Revathi Uddarajud9f23d92020-07-27 10:55:06 +05309565 if ((flags & AUDIO_INPUT_FLAG_VOIP_TX) != 0)
9566 in->usecase = USECASE_AUDIO_RECORD_VOIP_LOW_LATENCY;
9567 else
9568 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009569#endif
9570 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009571 if (!in->realtime) {
9572 in->config = pcm_config_audio_capture;
9573 frame_size = audio_stream_in_frame_size(&in->stream);
9574 buffer_size = get_input_buffer_size(config->sample_rate,
9575 config->format,
9576 channel_count,
9577 is_low_latency);
9578 in->config.period_size = buffer_size / frame_size;
9579 in->config.rate = config->sample_rate;
9580 in->af_period_multiplier = 1;
9581 } else {
9582 // period size is left untouched for rt mode playback
9583 in->config = pcm_config_audio_capture_rt;
9584 in->af_period_multiplier = af_period_multiplier;
9585 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009586 }
9587
9588 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9589 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9590 in->realtime = 0;
9591 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9592 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009593 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009594 in->stream.start = in_start;
9595 in->stream.stop = in_stop;
9596 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9597 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009598 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009599 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009600 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9601 in->config = pcm_config_audio_capture;
9602 frame_size = audio_stream_in_frame_size(&in->stream);
9603 buffer_size = get_input_buffer_size(config->sample_rate,
9604 config->format,
9605 channel_count,
9606 false /*is_low_latency*/);
9607 in->config.period_size = buffer_size / frame_size;
9608 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009609 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009610 switch (config->format) {
9611 case AUDIO_FORMAT_PCM_32_BIT:
9612 in->bit_width = 32;
9613 break;
9614 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9615 case AUDIO_FORMAT_PCM_8_24_BIT:
9616 in->bit_width = 24;
9617 break;
9618 default:
9619 in->bit_width = 16;
9620 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009621 } else if (is_single_device_type_equal(&in->device_list,
9622 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9623 is_single_device_type_equal(&in->device_list,
9624 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009625 if (config->sample_rate == 0)
9626 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9627 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9628 config->sample_rate != 8000) {
9629 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9630 ret = -EINVAL;
9631 goto err_open;
9632 }
9633 if (config->format == AUDIO_FORMAT_DEFAULT)
9634 config->format = AUDIO_FORMAT_PCM_16_BIT;
9635 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9636 config->format = AUDIO_FORMAT_PCM_16_BIT;
9637 ret = -EINVAL;
9638 goto err_open;
9639 }
9640
9641 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009642 if (adev->ha_proxy_enable &&
9643 is_single_device_type_equal(&in->device_list,
9644 AUDIO_DEVICE_IN_TELEPHONY_RX))
9645 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009646 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009647 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009648 in->af_period_multiplier = 1;
9649 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaac412b32020-01-03 15:00:14 +05309650 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009651 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9652 (config->sample_rate == 8000 ||
9653 config->sample_rate == 16000 ||
9654 config->sample_rate == 32000 ||
9655 config->sample_rate == 48000) &&
9656 channel_count == 1) {
9657 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9658 in->config = pcm_config_audio_capture;
9659 frame_size = audio_stream_in_frame_size(&in->stream);
9660 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9661 config->sample_rate,
9662 config->format,
9663 channel_count, false /*is_low_latency*/);
9664 in->config.period_size = buffer_size / frame_size;
9665 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9666 in->config.rate = config->sample_rate;
9667 in->af_period_multiplier = 1;
Mingshu Pangc2d65042021-01-14 16:19:10 +08009668 } else if (in->realtime) {
9669 in->config = pcm_config_audio_capture_rt;
9670 in->config.format = pcm_format_from_audio_format(config->format);
9671 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009672 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309673 int ret_val;
9674 pthread_mutex_lock(&adev->lock);
9675 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9676 in, config, &channel_mask_updated);
9677 pthread_mutex_unlock(&adev->lock);
9678
9679 if (!ret_val) {
9680 if (channel_mask_updated == true) {
9681 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9682 __func__, config->channel_mask);
9683 ret = -EINVAL;
9684 goto err_open;
9685 }
9686 ALOGD("%s: created multi-channel session succesfully",__func__);
9687 } else if (audio_extn_compr_cap_enabled() &&
9688 audio_extn_compr_cap_format_supported(config->format) &&
9689 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9690 audio_extn_compr_cap_init(in);
9691 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309692 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309693 if (ret)
9694 goto err_open;
9695 } else {
9696 in->config = pcm_config_audio_capture;
9697 in->config.rate = config->sample_rate;
9698 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309699 in->format = config->format;
9700 frame_size = audio_stream_in_frame_size(&in->stream);
9701 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009702 config->format,
9703 channel_count,
9704 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009705 /* prevent division-by-zero */
9706 if (frame_size == 0) {
9707 ALOGE("%s: Error frame_size==0", __func__);
9708 ret = -EINVAL;
9709 goto err_open;
9710 }
9711
Revathi Uddarajud2634032017-12-07 14:42:34 +05309712 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009713 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009714
Revathi Uddarajud2634032017-12-07 14:42:34 +05309715 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9716 /* optionally use VOIP usecase depending on config(s) */
9717 ret = adev_update_voice_comm_input_stream(in, config);
9718 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009719
Revathi Uddarajud2634032017-12-07 14:42:34 +05309720 if (ret) {
9721 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9722 goto err_open;
9723 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009724 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309725
9726 /* assign concurrent capture usecase if record has to caried out from
9727 * actual hardware input source */
9728 if (audio_extn_is_concurrent_capture_enabled() &&
9729 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309730 /* Acquire lock to avoid two concurrent use cases initialized to
9731 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009732
Samyak Jainc37062f2019-04-25 18:41:06 +05309733 if (in->usecase == USECASE_AUDIO_RECORD) {
9734 pthread_mutex_lock(&adev->lock);
9735 if (!(adev->pcm_record_uc_state)) {
9736 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9737 adev->pcm_record_uc_state = 1;
9738 pthread_mutex_unlock(&adev->lock);
9739 } else {
9740 pthread_mutex_unlock(&adev->lock);
9741 /* Assign compress record use case for second record */
9742 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9743 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9744 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9745 if (audio_extn_cin_applicable_stream(in)) {
9746 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309747 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309748 if (ret)
9749 goto err_open;
9750 }
9751 }
9752 }
kunleiz28c73e72019-03-27 17:24:04 +08009753 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009754 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309755 if (audio_extn_ssr_get_stream() != in)
9756 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009757
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009758 in->sample_rate = in->config.rate;
9759
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309760 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9761 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009762 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009763 in->sample_rate, in->bit_width,
9764 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309765 register_format(in->format, in->supported_formats);
9766 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9767 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309768
Aalique Grahame22e49102018-12-18 14:23:57 -08009769 in->error_log = error_log_create(
9770 ERROR_LOG_ENTRIES,
9771 1000000000 /* aggregate consecutive identical errors within one second */);
9772
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009773 /* This stream could be for sound trigger lab,
9774 get sound trigger pcm if present */
9775 audio_extn_sound_trigger_check_and_get_session(in);
9776
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309777 lock_input_stream(in);
9778 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9779 pthread_mutex_lock(&adev->lock);
9780 in->card_status = adev->card_status;
9781 pthread_mutex_unlock(&adev->lock);
9782 pthread_mutex_unlock(&in->lock);
9783
Aalique Grahame22e49102018-12-18 14:23:57 -08009784 stream_app_type_cfg_init(&in->app_type_cfg);
9785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009786 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009787
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009788 ret = io_streams_map_insert(adev, &in->stream.common,
9789 handle, AUDIO_PATCH_HANDLE_NONE);
9790 if (ret != 0)
9791 goto err_open;
9792
Susan Wang6dd13092021-01-25 10:27:11 -05009793 in->in_ctxt.input = in;
Derek Chenf939fb72018-11-13 13:34:41 -08009794
9795 pthread_mutex_lock(&adev->lock);
Susan Wang6dd13092021-01-25 10:27:11 -05009796 list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
Derek Chenf939fb72018-11-13 13:34:41 -08009797 pthread_mutex_unlock(&adev->lock);
9798
Eric Laurent994a6932013-07-17 11:51:42 -07009799 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009800 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009801
9802err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309803 if (in->usecase == USECASE_AUDIO_RECORD) {
9804 pthread_mutex_lock(&adev->lock);
9805 adev->pcm_record_uc_state = 0;
9806 pthread_mutex_unlock(&adev->lock);
9807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009808 free(in);
9809 *stream_in = NULL;
9810 return ret;
9811}
9812
9813static void adev_close_input_stream(struct audio_hw_device *dev,
9814 struct audio_stream_in *stream)
9815{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009816 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009817 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009818 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309819
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309820 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009821
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009822 if (in == NULL) {
9823 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9824 return;
9825 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009826 io_streams_map_remove(adev, in->capture_handle);
9827
Susan Wang6dd13092021-01-25 10:27:11 -05009828 // remove out_ctxt early to prevent the stream
9829 // being opened in a race condition
9830 pthread_mutex_lock(&adev->lock);
9831 list_remove(&in->in_ctxt.list);
9832 pthread_mutex_unlock(&adev->lock);
9833
kunleiz70e57612018-12-28 17:50:23 +08009834 /* must deregister from sndmonitor first to prevent races
9835 * between the callback and close_stream
9836 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309837 audio_extn_snd_mon_unregister_listener(stream);
9838
kunleiz70e57612018-12-28 17:50:23 +08009839 /* Disable echo reference if there are no active input, hfp call
9840 * and sound trigger while closing input stream
9841 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009842 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009843 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009844 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9845 struct listnode out_devices;
9846 list_init(&out_devices);
9847 platform_set_echo_reference(adev, false, &out_devices);
9848 } else
kunleiz70e57612018-12-28 17:50:23 +08009849 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309850
Weiyin Jiang2995f662019-04-17 14:25:12 +08009851 error_log_destroy(in->error_log);
9852 in->error_log = NULL;
9853
Pallavid7c7a272018-01-16 11:22:55 +05309854
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009855 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309856 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009857 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309858 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009859 if (ret != 0)
9860 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9861 __func__, ret);
9862 } else
9863 in_standby(&stream->common);
9864
Weiyin Jiang280ea742020-09-08 20:28:22 +08009865 pthread_mutex_destroy(&in->lock);
9866 pthread_mutex_destroy(&in->pre_lock);
9867
Revathi Uddarajud2634032017-12-07 14:42:34 +05309868 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309869 if (in->usecase == USECASE_AUDIO_RECORD) {
9870 adev->pcm_record_uc_state = 0;
9871 }
9872
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009873 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9874 adev->enable_voicerx = false;
9875 }
9876
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009877 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009878 audio_extn_ssr_deinit();
9879 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009880
Garmond Leunge2433c32017-09-28 21:51:22 -07009881 if (audio_extn_ffv_get_stream() == in) {
9882 audio_extn_ffv_stream_deinit();
9883 }
9884
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309885 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009886 audio_extn_compr_cap_format_supported(in->config.format))
9887 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309888
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309889 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309890 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009891
Mingming Yinfd7607b2016-01-22 12:48:44 -08009892 if (in->is_st_session) {
9893 ALOGV("%s: sound trigger pcm stop lab", __func__);
9894 audio_extn_sound_trigger_stop_lab(in);
9895 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009896 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309897 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009898 return;
9899}
9900
Aalique Grahame22e49102018-12-18 14:23:57 -08009901/* verifies input and output devices and their capabilities.
9902 *
9903 * This verification is required when enabling extended bit-depth or
9904 * sampling rates, as not all qcom products support it.
9905 *
9906 * Suitable for calling only on initialization such as adev_open().
9907 * It fills the audio_device use_case_table[] array.
9908 *
9909 * Has a side-effect that it needs to configure audio routing / devices
9910 * in order to power up the devices and read the device parameters.
9911 * It does not acquire any hw device lock. Should restore the devices
9912 * back to "normal state" upon completion.
9913 */
9914static int adev_verify_devices(struct audio_device *adev)
9915{
9916 /* enumeration is a bit difficult because one really wants to pull
9917 * the use_case, device id, etc from the hidden pcm_device_table[].
9918 * In this case there are the following use cases and device ids.
9919 *
9920 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9921 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9922 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9923 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9924 * [USECASE_AUDIO_RECORD] = {0, 0},
9925 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9926 * [USECASE_VOICE_CALL] = {2, 2},
9927 *
9928 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9929 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9930 */
9931
9932 /* should be the usecases enabled in adev_open_input_stream() */
9933 static const int test_in_usecases[] = {
9934 USECASE_AUDIO_RECORD,
9935 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9936 };
9937 /* should be the usecases enabled in adev_open_output_stream()*/
9938 static const int test_out_usecases[] = {
9939 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9940 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9941 };
9942 static const usecase_type_t usecase_type_by_dir[] = {
9943 PCM_PLAYBACK,
9944 PCM_CAPTURE,
9945 };
9946 static const unsigned flags_by_dir[] = {
9947 PCM_OUT,
9948 PCM_IN,
9949 };
9950
9951 size_t i;
9952 unsigned dir;
9953 const unsigned card_id = adev->snd_card;
9954
9955 for (dir = 0; dir < 2; ++dir) {
9956 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9957 const unsigned flags_dir = flags_by_dir[dir];
9958 const size_t testsize =
9959 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9960 const int *testcases =
9961 dir ? test_in_usecases : test_out_usecases;
9962 const audio_devices_t audio_device =
9963 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9964
9965 for (i = 0; i < testsize; ++i) {
9966 const audio_usecase_t audio_usecase = testcases[i];
9967 int device_id;
9968 struct pcm_params **pparams;
9969 struct stream_out out;
9970 struct stream_in in;
9971 struct audio_usecase uc_info;
9972 int retval;
9973
9974 pparams = &adev->use_case_table[audio_usecase];
9975 pcm_params_free(*pparams); /* can accept null input */
9976 *pparams = NULL;
9977
9978 /* find the device ID for the use case (signed, for error) */
9979 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9980 if (device_id < 0)
9981 continue;
9982
9983 /* prepare structures for device probing */
9984 memset(&uc_info, 0, sizeof(uc_info));
9985 uc_info.id = audio_usecase;
9986 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009987 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009988 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009989 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009990 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009991 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009992 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9993 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009994 }
9995 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009996 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009997 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009998 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009999 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -080010000 uc_info.in_snd_device = SND_DEVICE_NONE;
10001 uc_info.out_snd_device = SND_DEVICE_NONE;
10002 list_add_tail(&adev->usecase_list, &uc_info.list);
10003
10004 /* select device - similar to start_(in/out)put_stream() */
10005 retval = select_devices(adev, audio_usecase);
10006 if (retval >= 0) {
10007 *pparams = pcm_params_get(card_id, device_id, flags_dir);
10008#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -070010009 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -080010010 if (*pparams) {
10011 ALOGV("%s: (%s) card %d device %d", __func__,
10012 dir ? "input" : "output", card_id, device_id);
10013 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
10014 } else {
10015 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
10016 }
10017#endif
10018 }
10019
10020 /* deselect device - similar to stop_(in/out)put_stream() */
10021 /* 1. Get and set stream specific mixer controls */
10022 retval = disable_audio_route(adev, &uc_info);
10023 /* 2. Disable the rx device */
10024 retval = disable_snd_device(adev,
10025 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
10026 list_remove(&uc_info.list);
10027 }
10028 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010029 return 0;
10030}
10031
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032int update_patch(unsigned int num_sources,
10033 const struct audio_port_config *sources,
10034 unsigned int num_sinks,
10035 const struct audio_port_config *sinks,
10036 audio_patch_handle_t handle,
10037 struct audio_patch_info *p_info,
10038 patch_type_t patch_type, bool new_patch)
10039{
Aniket Kumar Latad13758f2020-08-06 15:11:36 -070010040 ALOGV("%s: enter", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010041
10042 if (p_info == NULL) {
10043 ALOGE("%s: Invalid patch pointer", __func__);
10044 return -EINVAL;
10045 }
10046
10047 if (new_patch) {
10048 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
10049 if (p_info->patch == NULL) {
10050 ALOGE("%s: Could not allocate patch", __func__);
10051 return -ENOMEM;
10052 }
10053 }
10054
10055 p_info->patch->id = handle;
10056 p_info->patch->num_sources = num_sources;
10057 p_info->patch->num_sinks = num_sinks;
10058
10059 for (int i = 0; i < num_sources; i++)
10060 p_info->patch->sources[i] = sources[i];
10061 for (int i = 0; i < num_sinks; i++)
10062 p_info->patch->sinks[i] = sinks[i];
10063
10064 p_info->patch_type = patch_type;
10065 return 0;
10066}
10067
10068audio_patch_handle_t generate_patch_handle()
10069{
10070 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
10071 if (++patch_handle < 0)
10072 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
10073 return patch_handle;
10074}
10075
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010076int adev_create_audio_patch(struct audio_hw_device *dev,
10077 unsigned int num_sources,
10078 const struct audio_port_config *sources,
10079 unsigned int num_sinks,
10080 const struct audio_port_config *sinks,
10081 audio_patch_handle_t *handle)
10082{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 int ret = 0;
10084 struct audio_device *adev = (struct audio_device *)dev;
10085 struct audio_patch_info *p_info = NULL;
10086 patch_type_t patch_type = PATCH_NONE;
10087 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10088 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10089 struct audio_stream_info *s_info = NULL;
10090 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010091 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010092 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10093 bool new_patch = false;
10094 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010095
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010096 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10097 num_sources, num_sinks, *handle);
10098
10099 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10100 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10101 ALOGE("%s: Invalid patch arguments", __func__);
10102 ret = -EINVAL;
10103 goto done;
10104 }
10105
10106 if (num_sources > 1) {
10107 ALOGE("%s: Multiple sources are not supported", __func__);
10108 ret = -EINVAL;
10109 goto done;
10110 }
10111
10112 if (sources == NULL || sinks == NULL) {
10113 ALOGE("%s: Invalid sources or sinks port config", __func__);
10114 ret = -EINVAL;
10115 goto done;
10116 }
10117
10118 ALOGV("%s: source role %d, source type %d", __func__,
10119 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010120 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010121
10122 // Populate source/sink information and fetch stream info
10123 switch (sources[0].type) {
10124 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10125 device_type = sources[0].ext.device.type;
10126 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010127 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10129 patch_type = PATCH_CAPTURE;
10130 io_handle = sinks[0].ext.mix.handle;
10131 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010132 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010133 __func__, device_type, io_handle);
10134 } else {
10135 // Device to device patch is not implemented.
10136 // This space will need changes if audio HAL
10137 // handles device to device patches in the future.
10138 patch_type = PATCH_DEVICE_LOOPBACK;
10139 }
10140 break;
10141 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10142 io_handle = sources[0].ext.mix.handle;
10143 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010144 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010145 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010146 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 }
10148 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010149 ALOGD("%s: Playback patch from mix handle %d to device %x",
10150 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010151 break;
10152 case AUDIO_PORT_TYPE_SESSION:
10153 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010154 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10155 ret = -EINVAL;
10156 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010157 }
10158
10159 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010160
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010161 // Generate patch info and update patch
10162 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010163 *handle = generate_patch_handle();
10164 p_info = (struct audio_patch_info *)
10165 calloc(1, sizeof(struct audio_patch_info));
10166 if (p_info == NULL) {
10167 ALOGE("%s: Failed to allocate memory", __func__);
10168 pthread_mutex_unlock(&adev->lock);
10169 ret = -ENOMEM;
10170 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010171 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010172 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010173 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010174 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 if (p_info == NULL) {
10176 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10177 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010178 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010179 ret = -EINVAL;
10180 goto done;
10181 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010182 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010183 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010184 *handle, p_info, patch_type, new_patch);
10185
10186 // Fetch stream info of associated mix for playback or capture patches
10187 if (p_info->patch_type == PATCH_PLAYBACK ||
10188 p_info->patch_type == PATCH_CAPTURE) {
10189 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10190 if (s_info == NULL) {
10191 ALOGE("%s: Failed to obtain stream info", __func__);
10192 if (new_patch)
10193 free(p_info);
10194 pthread_mutex_unlock(&adev->lock);
10195 ret = -EINVAL;
10196 goto done;
10197 }
10198 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10199 s_info->patch_handle = *handle;
10200 stream = s_info->stream;
10201 }
10202 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010203
10204 // Update routing for stream
10205 if (stream != NULL) {
10206 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010207 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010208 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010209 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010210 if (ret < 0) {
10211 pthread_mutex_lock(&adev->lock);
10212 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10213 if (new_patch)
10214 free(p_info);
10215 pthread_mutex_unlock(&adev->lock);
10216 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10217 goto done;
10218 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 }
10220
10221 // Add new patch to patch map
10222 if (!ret && new_patch) {
10223 pthread_mutex_lock(&adev->lock);
10224 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010225 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010226 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010227 }
10228
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010229done:
10230 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010231 num_sources,
10232 sources,
10233 num_sinks,
10234 sinks,
10235 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010236 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010237 num_sources,
10238 sources,
10239 num_sinks,
10240 sinks,
10241 handle);
10242 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010243}
10244
10245int adev_release_audio_patch(struct audio_hw_device *dev,
10246 audio_patch_handle_t handle)
10247{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010248 struct audio_device *adev = (struct audio_device *) dev;
10249 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010250 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010251 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010252
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010253 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10254 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10255 ret = -EINVAL;
10256 goto done;
10257 }
10258
10259 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010260 pthread_mutex_lock(&adev->lock);
10261 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010262 if (p_info == NULL) {
10263 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010264 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010265 ret = -EINVAL;
10266 goto done;
10267 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010268 struct audio_patch *patch = p_info->patch;
10269 if (patch == NULL) {
10270 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010271 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010272 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010273 goto done;
10274 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010275 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10276 switch (patch->sources[0].type) {
10277 case AUDIO_PORT_TYPE_MIX:
10278 io_handle = patch->sources[0].ext.mix.handle;
10279 break;
10280 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010281 if (p_info->patch_type == PATCH_CAPTURE)
10282 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010283 break;
10284 case AUDIO_PORT_TYPE_SESSION:
10285 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010286 pthread_mutex_unlock(&adev->lock);
10287 ret = -EINVAL;
10288 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010289 }
10290
10291 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010292 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010293 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010294 if (patch_type == PATCH_PLAYBACK ||
10295 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010296 struct audio_stream_info *s_info =
10297 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10298 if (s_info == NULL) {
10299 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10300 pthread_mutex_unlock(&adev->lock);
10301 goto done;
10302 }
10303 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10304 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010305 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010306 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010307
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010308 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010309 struct listnode devices;
10310 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010311 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010312 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010313 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010314 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010315 }
10316
10317 if (ret < 0)
10318 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10319
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010320done:
10321 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10322 audio_extn_auto_hal_release_audio_patch(dev, handle);
10323
10324 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010325 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010326}
10327
10328int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10329{
Derek Chenf13dd492018-11-13 14:53:51 -080010330 int ret = 0;
10331
10332 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10333 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10334 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010335}
10336
10337int adev_set_audio_port_config(struct audio_hw_device *dev,
10338 const struct audio_port_config *config)
10339{
Derek Chenf13dd492018-11-13 14:53:51 -080010340 int ret = 0;
10341
10342 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10343 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10344 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010345}
10346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010347static int adev_dump(const audio_hw_device_t *device __unused,
10348 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010349{
10350 return 0;
10351}
10352
10353static int adev_close(hw_device_t *device)
10354{
Aalique Grahame22e49102018-12-18 14:23:57 -080010355 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010356 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010357
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010358 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010359 return 0;
10360
10361 pthread_mutex_lock(&adev_init_lock);
10362
10363 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010364 if (audio_extn_spkr_prot_is_enabled())
10365 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010366 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010367 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010368 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010369 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010370 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010371 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010372 audio_extn_utils_release_streams_cfg_lists(
10373 &adev->streams_output_cfg_list,
10374 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010375 if (audio_extn_qap_is_enabled())
10376 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010377 if (audio_extn_qaf_is_enabled())
10378 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010379 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010380 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010381 free(adev->snd_dev_ref_cnt);
10382 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010383 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10384 pcm_params_free(adev->use_case_table[i]);
10385 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010386 if (adev->adm_deinit)
10387 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010388 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010389 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010390 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010391 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010392 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010393 if (adev->device_cfg_params) {
10394 free(adev->device_cfg_params);
10395 adev->device_cfg_params = NULL;
10396 }
Derek Chend2530072014-11-24 12:39:14 -080010397 if(adev->ext_hw_plugin)
10398 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010399 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010400 free_map(adev->patch_map);
10401 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010402 free(device);
10403 adev = NULL;
10404 }
10405 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010406 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010407 return 0;
10408}
10409
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010410/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10411 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10412 * just that it _might_ work.
10413 */
10414static int period_size_is_plausible_for_low_latency(int period_size)
10415{
10416 switch (period_size) {
10417 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010418 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010419 case 240:
10420 case 320:
10421 case 480:
10422 return 1;
10423 default:
10424 return 0;
10425 }
10426}
10427
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010428static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10429{
10430 bool is_snd_card_status = false;
10431 bool is_ext_device_status = false;
10432 char value[32];
10433 int card = -1;
10434 card_status_t status;
10435
10436 if (cookie != adev || !parms)
10437 return;
10438
10439 if (!parse_snd_card_status(parms, &card, &status)) {
10440 is_snd_card_status = true;
10441 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10442 is_ext_device_status = true;
10443 } else {
10444 // not a valid event
10445 return;
10446 }
10447
10448 pthread_mutex_lock(&adev->lock);
10449 if (card == adev->snd_card || is_ext_device_status) {
10450 if (is_snd_card_status && adev->card_status != status) {
Jaideep Sharmacb402512020-09-24 17:51:07 +053010451 ALOGD("%s card_status %d", __func__, status);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010452 adev->card_status = status;
10453 platform_snd_card_update(adev->platform, status);
10454 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010455 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010456 if (status == CARD_STATUS_OFFLINE)
10457 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010458 } else if (is_ext_device_status) {
10459 platform_set_parameters(adev->platform, parms);
10460 }
10461 }
10462 pthread_mutex_unlock(&adev->lock);
10463 return;
10464}
10465
Weiyin Jiang280ea742020-09-08 20:28:22 +080010466/* adev lock held */
10467int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010468{
10469 struct audio_usecase *uc_info;
Zhou Song407e5aa2020-12-27 19:13:04 +080010470 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010471 struct listnode devices;
Zhou Song407e5aa2020-12-27 19:13:04 +080010472 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010473
10474 uc_info = get_usecase_from_list(adev, out->usecase);
10475 if (uc_info == NULL) {
10476 ALOGE("%s: Could not find the usecase (%d) in the list",
10477 __func__, out->usecase);
10478 return -EINVAL;
10479 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010480 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010481
Zhou Songbaddf9f2020-11-20 13:57:39 +080010482 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10483 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010484
10485 if (restore) {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010486 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010487 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010488 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010489 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010490 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10491 select_devices(adev, uc_info->id);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010492
10493 if (is_offload_usecase(out->usecase)) {
10494 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiang280ea742020-09-08 20:28:22 +080010495 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010496 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10497 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10498 } else {
10499 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010500 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010501 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010502 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010503 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010504 } else {
Weiyin Jiang280ea742020-09-08 20:28:22 +080010505 pthread_mutex_lock(&out->latch_lock);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010506 // mute stream and switch to speaker if suspended
10507 if (!out->a2dp_muted && !out->standby) {
Zhou Songbaddf9f2020-11-20 13:57:39 +080010508 assign_devices(&devices, &out->device_list);
10509 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song407e5aa2020-12-27 19:13:04 +080010510 list_for_each(node, &adev->usecase_list) {
10511 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songe63b6fe2021-04-15 13:54:46 +080010512 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
10513 !is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songcf77af02021-05-14 18:21:14 +080010514 !is_sco_out_device_type(&usecase->stream.out->device_list) &&
Zhou Songe63b6fe2021-04-15 13:54:46 +080010515 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10516 usecase->out_snd_device)) {
Zhou Song407e5aa2020-12-27 19:13:04 +080010517 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10518 break;
10519 }
10520 }
Zhou Songcf77af02021-05-14 18:21:14 +080010521 if ((is_a2dp_out_device_type(&devices) && list_length(&devices) == 1) ||
10522 (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Zhou Song8edbbdb2021-01-14 16:48:03 +080010523 out->a2dp_muted = true;
10524 if (is_offload_usecase(out->usecase)) {
10525 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10526 compress_pause(out->compr);
10527 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010528 } else {
Weiyin Jiang906db3c2021-03-02 13:17:04 +080010529 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
10530 out_set_voip_volume(&out->stream, (float)0, (float)0);
10531 else
10532 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10533
Zhou Song8edbbdb2021-01-14 16:48:03 +080010534 /* wait for stale pcm drained before switching to speaker */
10535 uint32_t latency =
10536 (out->config.period_count * out->config.period_size * 1000) /
10537 (out->config.rate);
10538 usleep(latency * 1000);
10539 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010540 }
10541 select_devices(adev, out->usecase);
Zhou Song8edbbdb2021-01-14 16:48:03 +080010542 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10543 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Songbaddf9f2020-11-20 13:57:39 +080010544 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010545 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10546 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010547 }
Zhou Songbaddf9f2020-11-20 13:57:39 +080010548 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010549 }
Weiyin Jiang280ea742020-09-08 20:28:22 +080010550 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010551 }
10552 ALOGV("%s: exit", __func__);
10553 return 0;
10554}
10555
Haynes Mathew George01156f92018-04-13 15:29:54 -070010556void adev_on_battery_status_changed(bool charging)
10557{
10558 pthread_mutex_lock(&adev->lock);
10559 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10560 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010561 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010562 pthread_mutex_unlock(&adev->lock);
10563}
10564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010565static int adev_open(const hw_module_t *module, const char *name,
10566 hw_device_t **device)
10567{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010568 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010569 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010570 char mixer_ctl_name[128] = {0};
10571 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010572
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010573 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010574 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10575
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010576 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010577 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010578 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010579 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010580 ALOGD("%s: returning existing instance of adev", __func__);
10581 ALOGD("%s: exit", __func__);
10582 pthread_mutex_unlock(&adev_init_lock);
10583 return 0;
10584 }
10585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010586 adev = calloc(1, sizeof(struct audio_device));
10587
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010588 if (!adev) {
10589 pthread_mutex_unlock(&adev_init_lock);
10590 return -ENOMEM;
10591 }
10592
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010593 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10594
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010595 // register audio ext hidl at the earliest
10596 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010597#ifdef DYNAMIC_LOG_ENABLED
10598 register_for_dynamic_logging("hal");
10599#endif
10600
Derek Chenf939fb72018-11-13 13:34:41 -080010601 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010602 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010603 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10604 maj_version = atoi(value);
10605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010606 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010607 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010608 adev->device.common.module = (struct hw_module_t *)module;
10609 adev->device.common.close = adev_close;
10610
10611 adev->device.init_check = adev_init_check;
10612 adev->device.set_voice_volume = adev_set_voice_volume;
10613 adev->device.set_master_volume = adev_set_master_volume;
10614 adev->device.get_master_volume = adev_get_master_volume;
10615 adev->device.set_master_mute = adev_set_master_mute;
10616 adev->device.get_master_mute = adev_get_master_mute;
10617 adev->device.set_mode = adev_set_mode;
10618 adev->device.set_mic_mute = adev_set_mic_mute;
10619 adev->device.get_mic_mute = adev_get_mic_mute;
10620 adev->device.set_parameters = adev_set_parameters;
10621 adev->device.get_parameters = adev_get_parameters;
10622 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10623 adev->device.open_output_stream = adev_open_output_stream;
10624 adev->device.close_output_stream = adev_close_output_stream;
10625 adev->device.open_input_stream = adev_open_input_stream;
10626 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010627 adev->device.create_audio_patch = adev_create_audio_patch;
10628 adev->device.release_audio_patch = adev_release_audio_patch;
10629 adev->device.get_audio_port = adev_get_audio_port;
10630 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010631 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010632 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010633
10634 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010635 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010636 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010637 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010638 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010639 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010640 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010641 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010642 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010643 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010644 /* Init audio and voice feature */
10645 audio_extn_feature_init();
10646 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010647 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010648 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010649 list_init(&adev->active_inputs_list);
10650 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010651 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010652 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10653 audio_extn_utils_hash_eq);
10654 if (!adev->io_streams_map) {
10655 ALOGE("%s: Could not create io streams map", __func__);
10656 ret = -ENOMEM;
10657 goto adev_open_err;
10658 }
10659 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10660 audio_extn_utils_hash_eq);
10661 if (!adev->patch_map) {
10662 ALOGE("%s: Could not create audio patch map", __func__);
10663 ret = -ENOMEM;
10664 goto adev_open_err;
10665 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010666 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010667 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010668 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010669 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010670 adev->perf_lock_opts[0] = 0x101;
10671 adev->perf_lock_opts[1] = 0x20E;
10672 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010673 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010674 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010675 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010676 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010677 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010678
Zhou Song68ebc352019-12-05 17:11:15 +080010679 audio_extn_perf_lock_init();
10680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010681 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010682 adev->platform = platform_init(adev);
10683 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010684 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010685 ret = -EINVAL;
10686 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010687 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010688
Aalique Grahame22e49102018-12-18 14:23:57 -080010689 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010690 if (audio_extn_qap_is_enabled()) {
10691 ret = audio_extn_qap_init(adev);
10692 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010693 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010694 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010695 }
10696 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10697 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10698 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010699
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010700 if (audio_extn_qaf_is_enabled()) {
10701 ret = audio_extn_qaf_init(adev);
10702 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010703 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010704 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010705 }
10706
10707 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10708 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10709 }
10710
Derek Chenae7b0342019-02-08 15:17:04 -080010711 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010712 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10713
Eric Laurentc4aef752013-09-12 17:45:53 -070010714 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10715 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10716 if (adev->visualizer_lib == NULL) {
10717 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10718 } else {
10719 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10720 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010721 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010722 "visualizer_hal_start_output");
10723 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010724 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010725 "visualizer_hal_stop_output");
10726 }
10727 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010728 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010729 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010730 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010731 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010732 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010733 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010734
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010735 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10736 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10737 if (adev->offload_effects_lib == NULL) {
10738 ALOGE("%s: DLOPEN failed for %s", __func__,
10739 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10740 } else {
10741 ALOGV("%s: DLOPEN successful for %s", __func__,
10742 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10743 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010744 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010745 "offload_effects_bundle_hal_start_output");
10746 adev->offload_effects_stop_output =
10747 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10748 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010749 adev->offload_effects_set_hpx_state =
10750 (int (*)(bool))dlsym(adev->offload_effects_lib,
10751 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010752 adev->offload_effects_get_parameters =
10753 (void (*)(struct str_parms *, struct str_parms *))
10754 dlsym(adev->offload_effects_lib,
10755 "offload_effects_bundle_get_parameters");
10756 adev->offload_effects_set_parameters =
10757 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10758 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010759 }
10760 }
10761
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010762 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10763 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10764 if (adev->adm_lib == NULL) {
10765 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10766 } else {
10767 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10768 adev->adm_init = (adm_init_t)
10769 dlsym(adev->adm_lib, "adm_init");
10770 adev->adm_deinit = (adm_deinit_t)
10771 dlsym(adev->adm_lib, "adm_deinit");
10772 adev->adm_register_input_stream = (adm_register_input_stream_t)
10773 dlsym(adev->adm_lib, "adm_register_input_stream");
10774 adev->adm_register_output_stream = (adm_register_output_stream_t)
10775 dlsym(adev->adm_lib, "adm_register_output_stream");
10776 adev->adm_deregister_stream = (adm_deregister_stream_t)
10777 dlsym(adev->adm_lib, "adm_deregister_stream");
10778 adev->adm_request_focus = (adm_request_focus_t)
10779 dlsym(adev->adm_lib, "adm_request_focus");
10780 adev->adm_abandon_focus = (adm_abandon_focus_t)
10781 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010782 adev->adm_set_config = (adm_set_config_t)
10783 dlsym(adev->adm_lib, "adm_set_config");
10784 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10785 dlsym(adev->adm_lib, "adm_request_focus_v2");
10786 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10787 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10788 adev->adm_on_routing_change = (adm_on_routing_change_t)
10789 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010790 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10791 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010792 }
10793 }
10794
Aalique Grahame22e49102018-12-18 14:23:57 -080010795 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010796 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010797 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Kunlei Zhanga3c4cb02021-03-05 16:03:54 +080010798 adev->fluence_nn_usecase_id = USECASE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010799 //initialize this to false for now,
10800 //this will be set to true through set param
10801 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010802
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010803 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010804 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010805
10806 if (k_enable_extended_precision)
10807 adev_verify_devices(adev);
10808
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010809 adev->dsp_bit_width_enforce_mode =
10810 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010811
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010812 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10813 &adev->streams_output_cfg_list,
10814 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010815
Kiran Kandi910e1862013-10-29 13:29:42 -070010816 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010817
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010818 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010819 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010820 trial = atoi(value);
10821 if (period_size_is_plausible_for_low_latency(trial)) {
10822 pcm_config_low_latency.period_size = trial;
10823 pcm_config_low_latency.start_threshold = trial / 4;
10824 pcm_config_low_latency.avail_min = trial / 4;
10825 configured_low_latency_capture_period_size = trial;
10826 }
10827 }
ronghuiz93177262021-04-21 19:58:13 +080010828 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010829 trial = atoi(value);
10830 if (period_size_is_plausible_for_low_latency(trial)) {
10831 configured_low_latency_capture_period_size = trial;
10832 }
10833 }
10834
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010835 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10836
Eric Laurent4b084132018-10-19 17:33:43 -070010837 adev->camera_orientation = CAMERA_DEFAULT;
10838
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010839 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010840 af_period_multiplier = atoi(value);
10841 if (af_period_multiplier < 0)
10842 af_period_multiplier = 2;
10843 else if (af_period_multiplier > 4)
10844 af_period_multiplier = 4;
10845
10846 ALOGV("new period_multiplier = %d", af_period_multiplier);
10847 }
10848
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010849 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010850
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010851 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010852 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010853 pthread_mutex_unlock(&adev_init_lock);
10854
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010855 if (adev->adm_init)
10856 adev->adm_data = adev->adm_init();
10857
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010858 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010859 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010860
10861 audio_extn_snd_mon_init();
10862 pthread_mutex_lock(&adev->lock);
10863 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10864 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010865 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10866 /*
10867 * if the battery state callback happens before charging can be queried,
10868 * it will be guarded with the adev->lock held in the cb function and so
10869 * the callback value will reflect the latest state
10870 */
10871 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010872 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010873 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010874 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010875 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010876 /* Allocate memory for Device config params */
10877 adev->device_cfg_params = (struct audio_device_config_param*)
10878 calloc(platform_get_max_codec_backend(),
10879 sizeof(struct audio_device_config_param));
10880 if (adev->device_cfg_params == NULL)
10881 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010882
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010883 /*
10884 * Check if new PSPD matrix mixer control is supported. If not
10885 * supported, then set flag so that old mixer ctrl is sent while
10886 * sending pspd coefficients on older kernel version. Query mixer
10887 * control for default pcm id and channel value one.
10888 */
10889 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10890 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10891
10892 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10893 if (!ctl) {
10894 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10895 __func__, mixer_ctl_name);
10896 adev->use_old_pspd_mix_ctrl = true;
10897 }
10898
Jaideep Sharma0fa53812020-09-17 09:00:11 +053010899 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010900 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010901
10902adev_open_err:
10903 free_map(adev->patch_map);
10904 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010905 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010906 pthread_mutex_destroy(&adev->lock);
10907 free(adev);
10908 adev = NULL;
10909 *device = NULL;
10910 pthread_mutex_unlock(&adev_init_lock);
10911 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010912}
10913
10914static struct hw_module_methods_t hal_module_methods = {
10915 .open = adev_open,
10916};
10917
10918struct audio_module HAL_MODULE_INFO_SYM = {
10919 .common = {
10920 .tag = HARDWARE_MODULE_TAG,
10921 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10922 .hal_api_version = HARDWARE_HAL_API_VERSION,
10923 .id = AUDIO_HARDWARE_MODULE_ID,
10924 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010925 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010926 .methods = &hal_module_methods,
10927 },
10928};