blob: 3b784b8285de65dcbd0a4f887fe5b34aa40019b0 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shalini Manjunatha8ae54892020-12-29 13:02:25 +05302 * 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 Song1f93fa52020-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",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700424};
425
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426static const audio_usecase_t offload_usecases[] = {
427 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437
Varun Balaraje49253e2017-07-06 19:48:56 +0530438static const audio_usecase_t interactive_usecases[] = {
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
447};
448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449#define STRING_TO_ENUM(string) { #string, string }
450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451struct string_to_enum {
452 const char *name;
453 uint32_t value;
454};
455
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476};
477
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700478static const struct string_to_enum formats_name_to_enum_table[] = {
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700485 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800486 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
487 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800489};
490
491//list of all supported sample rates by HDMI specification.
492static const int out_hdmi_sample_rates[] = {
493 32000, 44100, 48000, 88200, 96000, 176400, 192000,
494};
495
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700496static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800497 STRING_TO_ENUM(32000),
498 STRING_TO_ENUM(44100),
499 STRING_TO_ENUM(48000),
500 STRING_TO_ENUM(88200),
501 STRING_TO_ENUM(96000),
502 STRING_TO_ENUM(176400),
503 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800504 STRING_TO_ENUM(352800),
505 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700506};
507
Carter Hsu2e429db2019-05-14 18:50:52 +0800508struct in_effect_list {
509 struct listnode list;
510 effect_handle_t handle;
511};
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700514static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700515static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700516//cache last MBDRC cal step level
517static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530519static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700520static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800521static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530522static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530523
Derek Chen6f293672019-04-01 01:40:24 -0700524static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
525static void in_snd_mon_cb(void * stream, struct str_parms * parms);
526static void out_snd_mon_cb(void * stream, struct str_parms * parms);
527
Zhou Song331c8e52019-08-26 14:16:12 +0800528static int configure_btsco_sample_rate(snd_device_t snd_device);
529
Vatsal Buchac09ae062018-11-14 13:25:08 +0530530#ifdef AUDIO_FEATURE_ENABLED_GCOV
531extern void __gcov_flush();
532static void enable_gcov()
533{
534 __gcov_flush();
535}
536#else
537static void enable_gcov()
538{
539}
540#endif
541
justinweng20fb6d82019-02-21 18:49:00 -0700542static int in_set_microphone_direction(const struct audio_stream_in *stream,
543 audio_microphone_direction_t dir);
544static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
545
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700546static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
547 int flags __unused)
548{
549 int dir = 0;
550 switch (uc_id) {
551 case USECASE_AUDIO_RECORD_LOW_LATENCY:
552 dir = 1;
553 case USECASE_AUDIO_PLAYBACK_ULL:
554 break;
555 default:
556 return false;
557 }
558
559 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
560 PCM_PLAYBACK : PCM_CAPTURE);
561 if (adev->adm_is_noirq_avail)
562 return adev->adm_is_noirq_avail(adev->adm_data,
563 adev->snd_card, dev_id, dir);
564 return false;
565}
566
567static void register_out_stream(struct stream_out *out)
568{
569 struct audio_device *adev = out->dev;
570 if (is_offload_usecase(out->usecase) ||
571 !adev->adm_register_output_stream)
572 return;
573
574 // register stream first for backward compatibility
575 adev->adm_register_output_stream(adev->adm_data,
576 out->handle,
577 out->flags);
578
579 if (!adev->adm_set_config)
580 return;
581
582 if (out->realtime)
583 adev->adm_set_config(adev->adm_data,
584 out->handle,
585 out->pcm, &out->config);
586}
587
588static void register_in_stream(struct stream_in *in)
589{
590 struct audio_device *adev = in->dev;
591 if (!adev->adm_register_input_stream)
592 return;
593
594 adev->adm_register_input_stream(adev->adm_data,
595 in->capture_handle,
596 in->flags);
597
598 if (!adev->adm_set_config)
599 return;
600
601 if (in->realtime)
602 adev->adm_set_config(adev->adm_data,
603 in->capture_handle,
604 in->pcm,
605 &in->config);
606}
607
608static void request_out_focus(struct stream_out *out, long ns)
609{
610 struct audio_device *adev = out->dev;
611
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700612 if (adev->adm_request_focus_v2)
613 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
614 else if (adev->adm_request_focus)
615 adev->adm_request_focus(adev->adm_data, out->handle);
616}
617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619{
620 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700621 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 if (adev->adm_request_focus_v2_1)
624 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
625 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus)
628 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629
630 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631}
632
633static void release_out_focus(struct stream_out *out)
634{
635 struct audio_device *adev = out->dev;
636
637 if (adev->adm_abandon_focus)
638 adev->adm_abandon_focus(adev->adm_data, out->handle);
639}
640
641static void release_in_focus(struct stream_in *in)
642{
643 struct audio_device *adev = in->dev;
644 if (adev->adm_abandon_focus)
645 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
646}
647
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530648static int parse_snd_card_status(struct str_parms *parms, int *card,
649 card_status_t *status)
650{
651 char value[32]={0};
652 char state[32]={0};
653
654 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
655 if (ret < 0)
656 return -1;
657
658 // sscanf should be okay as value is of max length 32.
659 // same as sizeof state.
660 if (sscanf(value, "%d,%s", card, state) < 2)
661 return -1;
662
663 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
664 CARD_STATUS_OFFLINE;
665 return 0;
666}
667
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668static inline void adjust_frames_for_device_delay(struct stream_out *out,
669 uint32_t *dsp_frames) {
670 // Adjustment accounts for A2dp encoder latency with offload usecases
671 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800672 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700673 unsigned long offset =
674 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
675 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
676 }
677}
678
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700679static inline bool free_entry(void *key __unused,
680 void *value, void *context __unused)
681{
682 free(value);
683 return true;
684}
685
686static inline void free_map(Hashmap *map)
687{
688 if (map) {
689 hashmapForEach(map, free_entry, (void *) NULL);
690 hashmapFree(map);
691 }
692}
693
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800694static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 audio_patch_handle_t patch_handle)
696{
697 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
698 return;
699
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700 struct audio_patch_info *p_info =
701 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
702 if (p_info) {
703 ALOGV("%s: Remove patch %d", __func__, patch_handle);
704 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
705 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700706 free(p_info);
707 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708}
709
710static inline int io_streams_map_insert(struct audio_device *adev,
711 struct audio_stream *stream,
712 audio_io_handle_t handle,
713 audio_patch_handle_t patch_handle)
714{
715 struct audio_stream_info *s_info =
716 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
717
718 if (s_info == NULL) {
719 ALOGE("%s: Could not allocate stream info", __func__);
720 return -ENOMEM;
721 }
722 s_info->stream = stream;
723 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724
725 pthread_mutex_lock(&adev->lock);
726 struct audio_stream_info *stream_info =
727 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700728 if (stream_info != NULL)
729 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800730 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700731 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
732 return 0;
733}
734
735static inline void io_streams_map_remove(struct audio_device *adev,
736 audio_io_handle_t handle)
737{
738 pthread_mutex_lock(&adev->lock);
739 struct audio_stream_info *s_info =
740 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700745 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746done:
747 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return;
749}
750
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 audio_patch_handle_t handle)
753{
754 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700755 p_info = (struct audio_patch_info *)
756 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return p_info;
758}
759
vivek mehtaa76401a2015-04-24 14:12:15 -0700760__attribute__ ((visibility ("default")))
761bool audio_hw_send_gain_dep_calibration(int level) {
762 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700763 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700764
765 pthread_mutex_lock(&adev_init_lock);
766
767 if (adev != NULL && adev->platform != NULL) {
768 pthread_mutex_lock(&adev->lock);
769 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700770
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530771 // cache level info for any of the use case which
772 // was not started.
773 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700774
vivek mehtaa76401a2015-04-24 14:12:15 -0700775 pthread_mutex_unlock(&adev->lock);
776 } else {
777 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
778 }
779
780 pthread_mutex_unlock(&adev_init_lock);
781
782 return ret_val;
783}
784
Ashish Jain5106d362016-05-11 19:23:33 +0530785static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
786{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787 bool gapless_enabled = false;
788 const char *mixer_ctl_name = "Compress Gapless Playback";
789 struct mixer_ctl *ctl;
790
791 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700792 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530793
794 /*Disable gapless if its AV playback*/
795 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796
797 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
798 if (!ctl) {
799 ALOGE("%s: Could not get ctl for mixer cmd - %s",
800 __func__, mixer_ctl_name);
801 return -EINVAL;
802 }
803
804 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
805 ALOGE("%s: Could not set gapless mode %d",
806 __func__, gapless_enabled);
807 return -EINVAL;
808 }
809 return 0;
810}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700811
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700812__attribute__ ((visibility ("default")))
813int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
814 int table_size) {
815 int ret_val = 0;
816 ALOGV("%s: enter ... ", __func__);
817
818 pthread_mutex_lock(&adev_init_lock);
819 if (adev == NULL) {
820 ALOGW("%s: adev is NULL .... ", __func__);
821 goto done;
822 }
823
824 pthread_mutex_lock(&adev->lock);
825 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
826 pthread_mutex_unlock(&adev->lock);
827done:
828 pthread_mutex_unlock(&adev_init_lock);
829 ALOGV("%s: exit ... ", __func__);
830 return ret_val;
831}
832
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800834{
835 bool ret = false;
836 ALOGV("%s: enter ...", __func__);
837
838 pthread_mutex_lock(&adev_init_lock);
839
840 if (adev != NULL && adev->platform != NULL) {
841 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800843 pthread_mutex_unlock(&adev->lock);
844 }
845
846 pthread_mutex_unlock(&adev_init_lock);
847
848 ALOGV("%s: exit with ret %d", __func__, ret);
849 return ret;
850}
Aalique Grahame22e49102018-12-18 14:23:57 -0800851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700852static bool is_supported_format(audio_format_t format)
853{
Eric Laurent86e17132013-09-12 17:49:30 -0700854 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530855 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530856 format == AUDIO_FORMAT_AAC_LC ||
857 format == AUDIO_FORMAT_AAC_HE_V1 ||
858 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530859 format == AUDIO_FORMAT_AAC_ADTS_LC ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
861 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530862 format == AUDIO_FORMAT_AAC_LATM_LC ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
864 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530865 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
866 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530867 format == AUDIO_FORMAT_PCM_FLOAT ||
868 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700869 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530870 format == AUDIO_FORMAT_AC3 ||
871 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700872 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530873 format == AUDIO_FORMAT_DTS ||
874 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530876 format == AUDIO_FORMAT_ALAC ||
877 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530878 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530879 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800880 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530881 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700882 format == AUDIO_FORMAT_APTX ||
883 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800884 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700885
886 return false;
887}
888
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700889static inline bool is_mmap_usecase(audio_usecase_t uc_id)
890{
891 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800892 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700893 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
894}
895
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700896static inline bool is_valid_volume(float left, float right)
897{
898 return ((left >= 0.0f && right >= 0.0f) ? true : false);
899}
900
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530901static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530902{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530903 ALOGV("%s", __func__);
904 audio_route_apply_and_update_path(adev->audio_route,
905 "asrc-mode");
906 adev->asrc_mode_enabled = true;
907}
908
909static void disable_asrc_mode(struct audio_device *adev)
910{
911 ALOGV("%s", __func__);
912 audio_route_reset_and_update_path(adev->audio_route,
913 "asrc-mode");
914 adev->asrc_mode_enabled = false;
915}
916
917/*
918 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
919 * 44.1 or Native DSD backends are enabled for any of current use case.
920 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
921 * - Disable current mix path use case(Headphone backend) and re-enable it with
922 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
923 * e.g. Naitve DSD or Headphone 44.1 -> + 48
924 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530925static void check_and_set_asrc_mode(struct audio_device *adev,
926 struct audio_usecase *uc_info,
927 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530928{
929 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530930 int i, num_new_devices = 0;
931 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
932 /*
933 *Split snd device for new combo use case
934 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
935 */
936 if (platform_split_snd_device(adev->platform,
937 snd_device,
938 &num_new_devices,
939 split_new_snd_devices) == 0) {
940 for (i = 0; i < num_new_devices; i++)
941 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
942 } else {
943 int new_backend_idx = platform_get_backend_index(snd_device);
944 if (((new_backend_idx == HEADPHONE_BACKEND) ||
945 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
946 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
947 !adev->asrc_mode_enabled) {
948 struct listnode *node = NULL;
949 struct audio_usecase *uc = NULL;
950 struct stream_out *curr_out = NULL;
951 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
952 int i, num_devices, ret = 0;
953 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530954
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530955 list_for_each(node, &adev->usecase_list) {
956 uc = node_to_item(node, struct audio_usecase, list);
957 curr_out = (struct stream_out*) uc->stream.out;
958 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
959 /*
960 *Split snd device for existing combo use case
961 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
962 */
963 ret = platform_split_snd_device(adev->platform,
964 uc->out_snd_device,
965 &num_devices,
966 split_snd_devices);
967 if (ret < 0 || num_devices == 0) {
968 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
969 split_snd_devices[0] = uc->out_snd_device;
970 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800971 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530972 for (i = 0; i < num_devices; i++) {
973 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
974 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
975 if((new_backend_idx == HEADPHONE_BACKEND) &&
976 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
977 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
978 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
979 __func__);
980 enable_asrc_mode(adev);
981 break;
982 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
983 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
984 (usecase_backend_idx == HEADPHONE_BACKEND)) {
985 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
986 __func__);
987 disable_audio_route(adev, uc);
988 disable_snd_device(adev, uc->out_snd_device);
989 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
990 if (new_backend_idx == DSD_NATIVE_BACKEND)
991 audio_route_apply_and_update_path(adev->audio_route,
992 "hph-true-highquality-mode");
993 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
994 (curr_out->bit_width >= 24))
995 audio_route_apply_and_update_path(adev->audio_route,
996 "hph-highquality-mode");
997 enable_asrc_mode(adev);
998 enable_snd_device(adev, uc->out_snd_device);
999 enable_audio_route(adev, uc);
1000 break;
1001 }
1002 }
1003 // reset split devices count
1004 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001005 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301006 if (adev->asrc_mode_enabled)
1007 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301008 }
1009 }
1010 }
1011}
1012
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001013static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1014 struct audio_effect_config effect_config,
1015 unsigned int param_value)
1016{
1017 char mixer_ctl_name[] = "Audio Effect";
1018 struct mixer_ctl *ctl;
1019 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001020 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001021
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001022 if (in == NULL) {
1023 ALOGE("%s: active input stream is NULL", __func__);
1024 return -EINVAL;
1025 }
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1028 if (!ctl) {
1029 ALOGE("%s: Could not get mixer ctl - %s",
1030 __func__, mixer_ctl_name);
1031 return -EINVAL;
1032 }
1033
1034 set_values[0] = 1; //0:Rx 1:Tx
1035 set_values[1] = in->app_type_cfg.app_type;
1036 set_values[2] = (long)effect_config.module_id;
1037 set_values[3] = (long)effect_config.instance_id;
1038 set_values[4] = (long)effect_config.param_id;
1039 set_values[5] = param_value;
1040
1041 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1042
1043 return 0;
1044
1045}
1046
1047static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1048 int effect_type, unsigned int *param_value)
1049{
1050 int ret = 0;
1051 struct audio_effect_config other_effect_config;
1052 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001053 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001054
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001055 if (in == NULL) {
1056 ALOGE("%s: active input stream is NULL", __func__);
1057 return -EINVAL;
1058 }
1059
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060 usecase = get_usecase_from_list(adev, in->usecase);
1061 if (!usecase)
1062 return -EINVAL;
1063
1064 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1065 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1066 if (ret < 0) {
1067 ALOGE("%s Failed to get effect params %d", __func__, ret);
1068 return ret;
1069 }
1070
1071 if (module_id == other_effect_config.module_id) {
1072 //Same module id for AEC/NS. Values need to be combined
1073 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1074 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1075 *param_value |= other_effect_config.param_value;
1076 }
1077 }
1078
1079 return ret;
1080}
1081
1082static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301083{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001084 struct audio_effect_config effect_config;
1085 struct audio_usecase *usecase = NULL;
1086 int ret = 0;
1087 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001088 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001089
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001090 if(!voice_extn_is_dynamic_ecns_enabled())
1091 return ENOSYS;
1092
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 if (!in) {
1094 ALOGE("%s: Invalid input stream", __func__);
1095 return -EINVAL;
1096 }
1097
1098 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1099
1100 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001101 if (usecase == NULL) {
1102 ALOGE("%s: Could not find the usecase (%d) in the list",
1103 __func__, in->usecase);
1104 return -EINVAL;
1105 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001106
1107 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1108 if (ret < 0) {
1109 ALOGE("%s Failed to get module id %d", __func__, ret);
1110 return ret;
1111 }
1112 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1113 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1114
1115 if(enable)
1116 param_value = effect_config.param_value;
1117
1118 /*Special handling for AEC & NS effects Param values need to be
1119 updated if module ids are same*/
1120
1121 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1122 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1123 if (ret < 0)
1124 return ret;
1125 }
1126
1127 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1128
1129 return ret;
1130}
1131
1132static void check_and_enable_effect(struct audio_device *adev)
1133{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001134 if(!voice_extn_is_dynamic_ecns_enabled())
1135 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001136
Eric Laurent637e2d42018-11-15 12:24:31 -08001137 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001138
Eric Laurent637e2d42018-11-15 12:24:31 -08001139 if (in != NULL && !in->standby) {
1140 if (in->enable_aec)
1141 enable_disable_effect(adev, EFFECT_AEC, true);
1142
1143 if (in->enable_ns &&
1144 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1145 enable_disable_effect(adev, EFFECT_NS, true);
1146 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147 }
1148}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001150int pcm_ioctl(struct pcm *pcm, int request, ...)
1151{
1152 va_list ap;
1153 void * arg;
1154 int pcm_fd = *(int*)pcm;
1155
1156 va_start(ap, request);
1157 arg = va_arg(ap, void *);
1158 va_end(ap);
1159
1160 return ioctl(pcm_fd, request, arg);
1161}
1162
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001163int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001164 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001167 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301168 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301169 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001170 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301171 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001172
1173 if (usecase == NULL)
1174 return -EINVAL;
1175
1176 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1177
Carter Hsu2e429db2019-05-14 18:50:52 +08001178 if (usecase->type == PCM_CAPTURE) {
1179 struct stream_in *in = usecase->stream.in;
1180 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001182
1183 if (in) {
1184 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001185 list_init(&out_devices);
1186 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 struct listnode *node;
1188 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1189 USECASE_AUDIO_PLAYBACK_VOIP);
1190 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001191 assign_devices(&out_devices,
1192 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001193 } else if (adev->primary_output &&
1194 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001195 assign_devices(&out_devices,
1196 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001197 } else {
1198 list_for_each(node, &adev->usecase_list) {
1199 uinfo = node_to_item(node, struct audio_usecase, list);
1200 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001201 assign_devices(&out_devices,
1202 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001203 break;
1204 }
1205 }
1206 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001207
1208 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001209 in->ec_opened = true;
1210 }
1211 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001212 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1213 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1214 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001215 snd_device = usecase->in_snd_device;
1216 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001219
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001220#ifdef DS1_DOLBY_DAP_ENABLED
1221 audio_extn_dolby_set_dmid(adev);
1222 audio_extn_dolby_set_endpoint(adev);
1223#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001224 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001225 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301226 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001227 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001228 if (audio_extn_is_maxx_audio_enabled())
1229 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301230 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Song1f93fa52020-11-20 13:57:39 +08001231 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1232 out = usecase->stream.out;
1233 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301234 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1235 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301236
1237 if (usecase->type == PCM_CAPTURE) {
1238 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001239 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301240 ALOGD("%s: set custom mtmx params v1", __func__);
1241 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1242 }
1243 } else {
1244 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1245 }
Manish Dewangan58229382017-02-02 15:48:41 +05301246
Andy Hung756ecc12018-10-19 17:47:12 -07001247 // we shouldn't truncate mixer_path
1248 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1249 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1250 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001251 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001252 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301253 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1254 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1255 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1256 if (parms) {
1257 audio_extn_fm_set_parameters(adev, parms);
1258 str_parms_destroy(parms);
1259 }
1260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 ALOGV("%s: exit", __func__);
1262 return 0;
1263}
1264
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001265int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001266 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001268 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001269 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301270 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001271
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301272 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001273 return -EINVAL;
1274
1275 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301276 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device = usecase->in_snd_device;
1278 else
1279 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001280
1281 /* disable island and power mode on supported device for voice call */
1282 if (usecase->type == VOICE_CALL) {
1283 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1284 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1285 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1286 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1287 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1288 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1289 ALOGD("%s: disable island cfg and power mode in voice tx path",
1290 __func__);
1291 }
1292 }
1293 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1294 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1295 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1296 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1297 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1298 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1299 ALOGD("%s: disable island cfg and power mode in voice rx path",
1300 __func__);
1301 }
1302 }
1303 }
1304
Andy Hung756ecc12018-10-19 17:47:12 -07001305 // we shouldn't truncate mixer_path
1306 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1307 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1308 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001309 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001310 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001311 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001312 if (usecase->type == PCM_CAPTURE) {
1313 struct stream_in *in = usecase->stream.in;
1314 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001315 struct listnode out_devices;
1316 list_init(&out_devices);
1317 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001318 in->ec_opened = false;
1319 }
1320 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001321 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301322 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301323
1324 if (usecase->type == PCM_CAPTURE) {
1325 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001326 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327 ALOGD("%s: reset custom mtmx params v1", __func__);
1328 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1329 }
1330 } else {
1331 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1332 }
1333
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001334 if ((usecase->type == PCM_PLAYBACK) &&
1335 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301336 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001338 ALOGV("%s: exit", __func__);
1339 return 0;
1340}
1341
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001342int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001343 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301345 int i, num_devices = 0;
1346 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001347 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1348
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001349 if (snd_device < SND_DEVICE_MIN ||
1350 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001351 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001352 return -EINVAL;
1353 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001355 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001356 ALOGE("%s: Invalid sound device returned", __func__);
1357 return -EINVAL;
1358 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001359
1360 adev->snd_dev_ref_cnt[snd_device]++;
1361
1362 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1363 (platform_split_snd_device(adev->platform,
1364 snd_device,
1365 &num_devices,
1366 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001367 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001368 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001369 /* Set backend config for A2DP to ensure slimbus configuration
1370 is correct if A2DP is already active and backend is closed
1371 and re-opened */
1372 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1373 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374 return 0;
1375 }
1376
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001377 if (audio_extn_spkr_prot_is_enabled())
1378 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001379
Aalique Grahame22e49102018-12-18 14:23:57 -08001380 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1381
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001382 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1383 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1385 goto err;
1386 }
1387 audio_extn_dev_arbi_acquire(snd_device);
1388 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001389 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001390 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001391 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001392 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001393 } else if (platform_split_snd_device(adev->platform,
1394 snd_device,
1395 &num_devices,
1396 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301397 for (i = 0; i < num_devices; i++) {
1398 enable_snd_device(adev, new_snd_devices[i]);
1399 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001400 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001402 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301403
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001404 /* enable island and power mode on supported device */
1405 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1406 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1407 platform_set_island_cfg_on_device(adev, snd_device, true);
1408 platform_set_power_mode_on_device(adev, snd_device, true);
1409 ALOGD("%s: enable island cfg and power mode on: %s",
1410 __func__, device_name);
1411 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301412
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301413 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1414 if (audio_extn_a2dp_start_playback() < 0) {
1415 ALOGE(" fail to configure A2dp Source control path ");
1416 goto err;
1417 } else {
1418 adev->a2dp_started = true;
1419 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001420 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001421
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1423 (audio_extn_a2dp_start_capture() < 0)) {
1424 ALOGE(" fail to configure A2dp Sink control path ");
1425 goto err;
1426 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301427
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001428 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1429 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1430 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1431 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1432 ALOGE(" fail to configure sco control path ");
1433 goto err;
1434 }
Zhou Song12c29502019-03-16 10:37:18 +08001435 }
1436
Zhou Song331c8e52019-08-26 14:16:12 +08001437 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001438 /* due to the possibility of calibration overwrite between listen
1439 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001440 audio_extn_sound_trigger_update_device_status(snd_device,
1441 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301442 audio_extn_listen_update_device_status(snd_device,
1443 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001444 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001445 audio_extn_sound_trigger_update_device_status(snd_device,
1446 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301447 audio_extn_listen_update_device_status(snd_device,
1448 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001449 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001450 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001451 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001452 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301453
1454 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1455 !adev->native_playback_enabled &&
1456 audio_is_true_native_stream_active(adev)) {
1457 ALOGD("%s: %d: napb: enabling native mode in hardware",
1458 __func__, __LINE__);
1459 audio_route_apply_and_update_path(adev->audio_route,
1460 "true-native-mode");
1461 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301462 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301463 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1464 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001465 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001466 ALOGD("%s: init ec ref loopback", __func__);
1467 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001471err:
1472 adev->snd_dev_ref_cnt[snd_device]--;
1473 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474}
1475
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001476int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001477 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301479 int i, num_devices = 0;
1480 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001483 if (snd_device < SND_DEVICE_MIN ||
1484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001486 return -EINVAL;
1487 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001488
1489 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1490 ALOGE("%s: Invalid sound device returned", __func__);
1491 return -EINVAL;
1492 }
1493
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1495 ALOGE("%s: device ref cnt is already 0", __func__);
1496 return -EINVAL;
1497 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001498
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001500
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001501
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001503 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301504
Aalique Grahame22e49102018-12-18 14:23:57 -08001505 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1506
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001507 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1508 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001509 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001510
1511 // when speaker device is disabled, reset swap.
1512 // will be renabled on usecase start
1513 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001514 } else if (platform_split_snd_device(adev->platform,
1515 snd_device,
1516 &num_devices,
1517 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301518 for (i = 0; i < num_devices; i++) {
1519 disable_snd_device(adev, new_snd_devices[i]);
1520 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001521 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001522 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001523 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001524 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001525
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301526 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301527 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301528 adev->a2dp_started = false;
1529 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001530 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001531 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301533 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301535 adev->native_playback_enabled) {
1536 ALOGD("%s: %d: napb: disabling native mode in hardware",
1537 __func__, __LINE__);
1538 audio_route_reset_and_update_path(adev->audio_route,
1539 "true-native-mode");
1540 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001541 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301542 adev->asrc_mode_enabled) {
1543 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301544 disable_asrc_mode(adev);
1545 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301547 (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: deinit ec ref loopback", __func__);
1550 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1551 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001552
1553 audio_extn_utils_release_snd_device(snd_device);
1554 } else {
1555 if (platform_split_snd_device(adev->platform,
1556 snd_device,
1557 &num_devices,
1558 new_snd_devices) == 0) {
1559 for (i = 0; i < num_devices; i++) {
1560 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1561 }
1562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 return 0;
1566}
1567
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001568/*
1569 legend:
1570 uc - existing usecase
1571 new_uc - new usecase
1572 d1, d11, d2 - SND_DEVICE enums
1573 a1, a2 - corresponding ANDROID device enums
1574 B1, B2 - backend strings
1575
1576case 1
1577 uc->dev d1 (a1) B1
1578 new_uc->dev d1 (a1), d2 (a2) B1, B2
1579
1580 resolution: disable and enable uc->dev on d1
1581
1582case 2
1583 uc->dev d1 (a1) B1
1584 new_uc->dev d11 (a1) B1
1585
1586 resolution: need to switch uc since d1 and d11 are related
1587 (e.g. speaker and voice-speaker)
1588 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1589
1590case 3
1591 uc->dev d1 (a1) B1
1592 new_uc->dev d2 (a2) B2
1593
1594 resolution: no need to switch uc
1595
1596case 4
1597 uc->dev d1 (a1) B1
1598 new_uc->dev d2 (a2) B1
1599
1600 resolution: disable enable uc-dev on d2 since backends match
1601 we cannot enable two streams on two different devices if they
1602 share the same backend. e.g. if offload is on speaker device using
1603 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1604 using the same backend, offload must also be switched to voice-handset.
1605
1606case 5
1607 uc->dev d1 (a1) B1
1608 new_uc->dev d1 (a1), d2 (a2) B1
1609
1610 resolution: disable enable uc-dev on d2 since backends match
1611 we cannot enable two streams on two different devices if they
1612 share the same backend.
1613
1614case 6
1615 uc->dev d1 (a1) B1
1616 new_uc->dev d2 (a1) B2
1617
1618 resolution: no need to switch
1619
1620case 7
1621 uc->dev d1 (a1), d2 (a2) B1, B2
1622 new_uc->dev d1 (a1) B1
1623
1624 resolution: no need to switch
1625
Zhou Song4ba65882018-07-09 14:48:07 +08001626case 8
1627 uc->dev d1 (a1) B1
1628 new_uc->dev d11 (a1), d2 (a2) B1, B2
1629 resolution: compared to case 1, for this case, d1 and d11 are related
1630 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301631
1632case 9
1633 uc->dev d1 (a1), d2(a2) B1 B2
1634 new_uc->dev d1 (a1), d22 (a2) B1, B2
1635 resolution: disable enable uc-dev on d2 since backends match
1636 we cannot enable two streams on two different devices if they
1637 share the same backend. This is special case for combo use case
1638 with a2dp and sco devices which uses same backend.
1639 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001640*/
1641static snd_device_t derive_playback_snd_device(void * platform,
1642 struct audio_usecase *uc,
1643 struct audio_usecase *new_uc,
1644 snd_device_t new_snd_device)
1645{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001646 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001647
1648 snd_device_t d1 = uc->out_snd_device;
1649 snd_device_t d2 = new_snd_device;
1650
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001651 list_init(&a1);
1652 list_init(&a2);
1653
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301654 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301655 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1657 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 break;
1659 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001660 assign_devices(&a1, &uc->stream.out->device_list);
1661 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301662 break;
1663 }
1664
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001665 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001666 if (!compare_devices(&a1, &a2) &&
1667 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001668 snd_device_t d3[2];
1669 int num_devices = 0;
1670 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001671 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001672 &num_devices,
1673 d3);
1674 if (ret < 0) {
1675 if (ret != -ENOSYS) {
1676 ALOGW("%s failed to split snd_device %d",
1677 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001679 }
1680 goto end;
1681 }
1682
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001683 if (platform_check_backends_match(d3[0], d3[1])) {
1684 return d2; // case 5
1685 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301686 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1687 platform_check_backends_match(d1, d2))
1688 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001689 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301690 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001691 // check if d1 is related to any of d3's
1692 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001693 return d1; // case 1
1694 else
1695 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001696 }
1697 } else {
1698 if (platform_check_backends_match(d1, d2)) {
1699 return d2; // case 2, 4
1700 } else {
1701 return d1; // case 6, 3
1702 }
1703 }
1704
1705end:
1706 return d2; // return whatever was calculated before.
1707}
1708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301710 struct audio_usecase *uc_info,
1711 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712{
1713 struct listnode *node;
1714 struct audio_usecase *usecase;
1715 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301716 snd_device_t uc_derive_snd_device;
1717 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001718 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1719 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001720 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301721 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001722 /*
1723 * This function is to make sure that all the usecases that are active on
1724 * the hardware codec backend are always routed to any one device that is
1725 * handled by the hardware codec.
1726 * For example, if low-latency and deep-buffer usecases are currently active
1727 * on speaker and out_set_parameters(headset) is received on low-latency
1728 * output, then we have to make sure deep-buffer is also switched to headset,
1729 * because of the limitation that both the devices cannot be enabled
1730 * at the same time as they share the same backend.
1731 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001732 /*
1733 * This call is to check if we need to force routing for a particular stream
1734 * If there is a backend configuration change for the device when a
1735 * new stream starts, then ADM needs to be closed and re-opened with the new
1736 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001737 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001738 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001739 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1740 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301741 /* For a2dp device reconfigure all active sessions
1742 * with new AFE encoder format based on a2dp state
1743 */
1744 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301745 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1746 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301747 audio_extn_a2dp_is_force_device_switch()) {
1748 force_routing = true;
1749 force_restart_session = true;
1750 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001751
1752 /*
1753 * Island cfg and power mode config needs to set before AFE port start.
1754 * Set force routing in case of voice device was enable before.
1755 */
1756 if (uc_info->type == VOICE_CALL &&
1757 voice_extn_is_voice_power_mode_supported() &&
1758 platform_check_and_update_island_power_status(adev->platform,
1759 uc_info,
1760 snd_device)) {
1761 force_routing = true;
1762 ALOGD("%s:becf: force routing %d for power mode supported device",
1763 __func__, force_routing);
1764 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301765 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1766
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001768 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001769 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1771 switch_device[i] = false;
1772
1773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001775
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301776 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1777 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301778 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301779 platform_get_snd_device_name(usecase->out_snd_device),
1780 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301781 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1782 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301783 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1784 usecase, uc_info, snd_device);
1785 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001786 (is_codec_backend_out_device_type(&usecase->device_list) ||
1787 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1788 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1789 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1790 is_a2dp_out_device_type(&usecase->device_list) ||
1791 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301792 ((force_restart_session) ||
1793 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301794 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1795 __func__, use_case_table[usecase->id],
1796 platform_get_snd_device_name(usecase->out_snd_device));
1797 disable_audio_route(adev, usecase);
1798 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301799 /* Enable existing usecase on derived playback device */
1800 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301801 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301802 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803 }
1804 }
1805
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301806 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1807 num_uc_to_switch);
1808
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001809 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001810 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301812 /* Make sure the previous devices to be disabled first and then enable the
1813 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 list_for_each(node, &adev->usecase_list) {
1815 usecase = node_to_item(node, struct audio_usecase, list);
1816 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001817 /* Check if output sound device to be switched can be split and if any
1818 of the split devices match with derived sound device */
1819 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1820 &num_devices, split_snd_devices) == 0) {
1821 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1822 for (i = 0; i < num_devices; i++) {
1823 /* Disable devices that do not match with derived sound device */
1824 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1825 disable_snd_device(adev, split_snd_devices[i]);
1826 }
1827 } else {
1828 disable_snd_device(adev, usecase->out_snd_device);
1829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 }
1831 }
1832
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001833 list_for_each(node, &adev->usecase_list) {
1834 usecase = node_to_item(node, struct audio_usecase, list);
1835 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001836 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1837 &num_devices, split_snd_devices) == 0) {
1838 /* Enable derived sound device only if it does not match with
1839 one of the split sound devices. This is because the matching
1840 sound device was not disabled */
1841 bool should_enable = true;
1842 for (i = 0; i < num_devices; i++) {
1843 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1844 should_enable = false;
1845 break;
1846 }
1847 }
1848 if (should_enable)
1849 enable_snd_device(adev, derive_snd_device[usecase->id]);
1850 } else {
1851 enable_snd_device(adev, derive_snd_device[usecase->id]);
1852 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001853 }
1854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 /* Re-route all the usecases on the shared backend other than the
1857 specified usecase to new snd devices */
1858 list_for_each(node, &adev->usecase_list) {
1859 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301860 /* Update the out_snd_device only before enabling the audio route */
1861 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301862 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301863 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1864 use_case_table[usecase->id],
1865 platform_get_snd_device_name(usecase->out_snd_device));
1866 /* Update voc calibration before enabling Voice/VoIP route */
1867 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1868 status = platform_switch_voice_call_device_post(adev->platform,
1869 usecase->out_snd_device,
1870 platform_get_input_snd_device(
1871 adev->platform, NULL,
1872 &uc_info->device_list,
1873 usecase->type));
1874 enable_audio_route(adev, usecase);
1875 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1876 out_set_voip_volume(&usecase->stream.out->stream,
1877 usecase->stream.out->volume_l,
1878 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880 }
1881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 }
1883}
1884
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301885static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001886 struct audio_usecase *uc_info,
1887 snd_device_t snd_device)
1888{
1889 struct listnode *node;
1890 struct audio_usecase *usecase;
1891 bool switch_device[AUDIO_USECASE_MAX];
1892 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001893 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001894 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001895
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301896 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1897 snd_device);
1898 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301899
1900 /*
1901 * Make sure out devices is checked against out codec backend device and
1902 * also in devices against in codec backend. Checking out device against in
1903 * codec backend or vice versa causes issues.
1904 */
1905 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001906 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001907
1908 /*
1909 * Island cfg and power mode config needs to set before AFE port start.
1910 * Set force routing in case of voice device was enable before.
1911 */
1912
1913 if (uc_info->type == VOICE_CALL &&
1914 voice_extn_is_voice_power_mode_supported() &&
1915 platform_check_and_update_island_power_status(adev->platform,
1916 uc_info,
1917 snd_device)) {
1918 force_routing = true;
1919 ALOGD("%s:becf: force routing %d for power mode supported device",
1920 __func__, force_routing);
1921 }
1922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 /*
1924 * This function is to make sure that all the active capture usecases
1925 * are always routed to the same input sound device.
1926 * For example, if audio-record and voice-call usecases are currently
1927 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1928 * is received for voice call then we have to make sure that audio-record
1929 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1930 * because of the limitation that two devices cannot be enabled
1931 * at the same time if they share the same backend.
1932 */
1933 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1934 switch_device[i] = false;
1935
1936 list_for_each(node, &adev->usecase_list) {
1937 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301938 /*
1939 * TODO: Enhance below condition to handle BT sco/USB multi recording
1940 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301941
1942 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1943 (usecase->in_snd_device != snd_device || force_routing));
1944 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1945 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1946 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001947 ((backend_check_cond &&
1948 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001949 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001950 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001951 is_single_device_type_equal(&usecase->device_list,
1952 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001953 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001954 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001955 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301956 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001957 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001958 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001959 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001960 switch_device[usecase->id] = true;
1961 num_uc_to_switch++;
1962 }
1963 }
1964
1965 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001966 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001967
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301968 /* Make sure the previous devices to be disabled first and then enable the
1969 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001970 list_for_each(node, &adev->usecase_list) {
1971 usecase = node_to_item(node, struct audio_usecase, list);
1972 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001973 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001974 }
1975 }
1976
1977 list_for_each(node, &adev->usecase_list) {
1978 usecase = node_to_item(node, struct audio_usecase, list);
1979 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001981 }
1982 }
1983
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001984 /* Re-route all the usecases on the shared backend other than the
1985 specified usecase to new snd devices */
1986 list_for_each(node, &adev->usecase_list) {
1987 usecase = node_to_item(node, struct audio_usecase, list);
1988 /* Update the in_snd_device only before enabling the audio route */
1989 if (switch_device[usecase->id] ) {
1990 usecase->in_snd_device = snd_device;
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301991 /* Update voc calibration before enabling Voice/VoIP route */
1992 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1993 snd_device_t voip_snd_device;
1994 voip_snd_device = platform_get_output_snd_device(adev->platform,
1995 usecase->stream.out,
1996 usecase->type);
1997 status = platform_switch_voice_call_device_post(adev->platform,
1998 voip_snd_device,
1999 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002000 }
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302001 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002002 }
2003 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002004 }
2005}
2006
Mingming Yin3a941d42016-02-17 18:08:05 -08002007static void reset_hdmi_sink_caps(struct stream_out *out) {
2008 int i = 0;
2009
2010 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2011 out->supported_channel_masks[i] = 0;
2012 }
2013 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2014 out->supported_formats[i] = 0;
2015 }
2016 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2017 out->supported_sample_rates[i] = 0;
2018 }
2019}
2020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002022static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023{
Mingming Yin3a941d42016-02-17 18:08:05 -08002024 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002025 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2026 out->extconn.cs.controller,
2027 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028
Mingming Yin3a941d42016-02-17 18:08:05 -08002029 reset_hdmi_sink_caps(out);
2030
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002031 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002032 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002033 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002034 out->extconn.cs.stream);
2035 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002036 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002037 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002038 }
2039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002042 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002043 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002044 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2045 case 6:
2046 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2047 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2048 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2049 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2050 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2051 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 break;
2053 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002054 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002055 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 break;
2057 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002058
2059 // check channel format caps
2060 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002061 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2062 out->extconn.cs.controller,
2063 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002064 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2065 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2066 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2067 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2068 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2069 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2070 }
2071
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002072 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2073 out->extconn.cs.controller,
2074 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002075 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2076 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2077 }
2078
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002079 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2080 out->extconn.cs.controller,
2081 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002082 ALOGV(":%s HDMI supports DTS format", __func__);
2083 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2084 }
2085
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002086 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2087 out->extconn.cs.controller,
2088 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002089 ALOGV(":%s HDMI supports DTS HD format", __func__);
2090 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2091 }
2092
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002093 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2094 out->extconn.cs.controller,
2095 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002096 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2097 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2098 }
2099
Mingming Yin3a941d42016-02-17 18:08:05 -08002100
2101 // check sample rate caps
2102 i = 0;
2103 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002104 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2105 out->extconn.cs.controller,
2106 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002107 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2108 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2109 }
2110 }
2111
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002112 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113}
2114
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002115static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2116 uint32_t *supported_sample_rates __unused,
2117 uint32_t max_rates __unused)
2118{
2119 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2120 supported_sample_rates,
2121 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302122 ssize_t i = 0;
2123
2124 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002125 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2126 supported_sample_rates[i]);
2127 }
2128 return count;
2129}
2130
2131static inline int read_usb_sup_channel_masks(bool is_playback,
2132 audio_channel_mask_t *supported_channel_masks,
2133 uint32_t max_masks)
2134{
2135 int channels = audio_extn_usb_get_max_channels(is_playback);
2136 int channel_count;
2137 uint32_t num_masks = 0;
2138 if (channels > MAX_HIFI_CHANNEL_COUNT)
2139 channels = MAX_HIFI_CHANNEL_COUNT;
2140
2141 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002142 // start from 2 channels as framework currently doesn't support mono.
2143 if (channels >= FCC_2) {
2144 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2145 }
2146 for (channel_count = FCC_2;
2147 channel_count <= channels && num_masks < max_masks;
2148 ++channel_count) {
2149 supported_channel_masks[num_masks++] =
2150 audio_channel_mask_for_index_assignment_from_count(channel_count);
2151 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002152 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002153 // For capture we report all supported channel masks from 1 channel up.
2154 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002155 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2156 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002157 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2158 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2159 if (channel_count <= FCC_2) {
2160 mask = audio_channel_in_mask_from_count(channel_count);
2161 supported_channel_masks[num_masks++] = mask;
2162 }
2163 const audio_channel_mask_t index_mask =
2164 audio_channel_mask_for_index_assignment_from_count(channel_count);
2165 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2166 supported_channel_masks[num_masks++] = index_mask;
2167 }
2168 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002169 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302170
vincenttewf51c94e2019-05-07 10:28:53 +08002171 for (size_t i = 0; i < num_masks; ++i) {
2172 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2173 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302174 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002175 return num_masks;
2176}
2177
2178static inline int read_usb_sup_formats(bool is_playback __unused,
2179 audio_format_t *supported_formats,
2180 uint32_t max_formats __unused)
2181{
2182 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2183 switch (bitwidth) {
2184 case 24:
2185 // XXX : usb.c returns 24 for s24 and s24_le?
2186 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2187 break;
2188 case 32:
2189 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2190 break;
2191 case 16:
2192 default :
2193 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2194 break;
2195 }
2196 ALOGV("%s: %s supported format %d", __func__,
2197 is_playback ? "P" : "C", bitwidth);
2198 return 1;
2199}
2200
2201static inline int read_usb_sup_params_and_compare(bool is_playback,
2202 audio_format_t *format,
2203 audio_format_t *supported_formats,
2204 uint32_t max_formats,
2205 audio_channel_mask_t *mask,
2206 audio_channel_mask_t *supported_channel_masks,
2207 uint32_t max_masks,
2208 uint32_t *rate,
2209 uint32_t *supported_sample_rates,
2210 uint32_t max_rates) {
2211 int ret = 0;
2212 int num_formats;
2213 int num_masks;
2214 int num_rates;
2215 int i;
2216
2217 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2218 max_formats);
2219 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2220 max_masks);
2221
2222 num_rates = read_usb_sup_sample_rates(is_playback,
2223 supported_sample_rates, max_rates);
2224
2225#define LUT(table, len, what, dflt) \
2226 for (i=0; i<len && (table[i] != what); i++); \
2227 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2228
2229 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2230 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2231 LUT(supported_sample_rates, num_rates, *rate, 0);
2232
2233#undef LUT
2234 return ret < 0 ? -EINVAL : 0; // HACK TBD
2235}
2236
Alexy Josephb1379942016-01-29 15:49:38 -08002237audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002238 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002239{
2240 struct audio_usecase *usecase;
2241 struct listnode *node;
2242
2243 list_for_each(node, &adev->usecase_list) {
2244 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002245 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002246 ALOGV("%s: usecase id %d", __func__, usecase->id);
2247 return usecase->id;
2248 }
2249 }
2250 return USECASE_INVALID;
2251}
2252
Alexy Josephb1379942016-01-29 15:49:38 -08002253struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002254 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255{
2256 struct audio_usecase *usecase;
2257 struct listnode *node;
2258
2259 list_for_each(node, &adev->usecase_list) {
2260 usecase = node_to_item(node, struct audio_usecase, list);
2261 if (usecase->id == uc_id)
2262 return usecase;
2263 }
2264 return NULL;
2265}
2266
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302267/*
2268 * is a true native playback active
2269 */
2270bool audio_is_true_native_stream_active(struct audio_device *adev)
2271{
2272 bool active = false;
2273 int i = 0;
2274 struct listnode *node;
2275
2276 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2277 ALOGV("%s:napb: not in true mode or non hdphones device",
2278 __func__);
2279 active = false;
2280 goto exit;
2281 }
2282
2283 list_for_each(node, &adev->usecase_list) {
2284 struct audio_usecase *uc;
2285 uc = node_to_item(node, struct audio_usecase, list);
2286 struct stream_out *curr_out =
2287 (struct stream_out*) uc->stream.out;
2288
2289 if (curr_out && PCM_PLAYBACK == uc->type) {
2290 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2291 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2292 uc->id, curr_out->sample_rate,
2293 curr_out->bit_width,
2294 platform_get_snd_device_name(uc->out_snd_device));
2295
2296 if (is_offload_usecase(uc->id) &&
2297 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2298 active = true;
2299 ALOGD("%s:napb:native stream detected", __func__);
2300 }
2301 }
2302 }
2303exit:
2304 return active;
2305}
2306
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002307uint32_t adev_get_dsp_bit_width_enforce_mode()
2308{
2309 if (adev == NULL) {
2310 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2311 return 0;
2312 }
2313 return adev->dsp_bit_width_enforce_mode;
2314}
2315
2316static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2317{
2318 char value[PROPERTY_VALUE_MAX];
2319 int trial;
2320 uint32_t dsp_bit_width_enforce_mode = 0;
2321
2322 if (!mixer) {
2323 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2324 __func__);
2325 return 0;
2326 }
2327
2328 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2329 value, NULL) > 0) {
2330 trial = atoi(value);
2331 switch (trial) {
2332 case 16:
2333 dsp_bit_width_enforce_mode = 16;
2334 break;
2335 case 24:
2336 dsp_bit_width_enforce_mode = 24;
2337 break;
2338 case 32:
2339 dsp_bit_width_enforce_mode = 32;
2340 break;
2341 default:
2342 dsp_bit_width_enforce_mode = 0;
2343 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2344 break;
2345 }
2346 }
2347
2348 return dsp_bit_width_enforce_mode;
2349}
2350
2351static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2352 uint32_t enforce_mode,
2353 bool enable)
2354{
2355 struct mixer_ctl *ctl = NULL;
2356 const char *mixer_ctl_name = "ASM Bit Width";
2357 uint32_t asm_bit_width_mode = 0;
2358
2359 if (enforce_mode == 0) {
2360 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2361 return;
2362 }
2363
2364 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2365 if (!ctl) {
2366 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2367 __func__, mixer_ctl_name);
2368 return;
2369 }
2370
2371 if (enable)
2372 asm_bit_width_mode = enforce_mode;
2373 else
2374 asm_bit_width_mode = 0;
2375
2376 ALOGV("%s DSP bit width feature status is %d width=%d",
2377 __func__, enable, asm_bit_width_mode);
2378 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2379 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2380 asm_bit_width_mode);
2381
2382 return;
2383}
2384
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302385/*
2386 * if native DSD playback active
2387 */
2388bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2389{
2390 bool active = false;
2391 struct listnode *node = NULL;
2392 struct audio_usecase *uc = NULL;
2393 struct stream_out *curr_out = NULL;
2394
2395 list_for_each(node, &adev->usecase_list) {
2396 uc = node_to_item(node, struct audio_usecase, list);
2397 curr_out = (struct stream_out*) uc->stream.out;
2398
2399 if (curr_out && PCM_PLAYBACK == uc->type &&
2400 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2401 active = true;
2402 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302403 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302404 }
2405 }
2406 return active;
2407}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302408
2409static bool force_device_switch(struct audio_usecase *usecase)
2410{
2411 bool ret = false;
2412 bool is_it_true_mode = false;
2413
Zhou Song30f2c3e2018-02-08 14:02:15 +08002414 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302415 usecase->type == TRANSCODE_LOOPBACK_RX ||
2416 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002417 return false;
2418 }
2419
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002420 if(usecase->stream.out == NULL) {
2421 ALOGE("%s: stream.out is NULL", __func__);
2422 return false;
2423 }
2424
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302425 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002426 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002427 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2428 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302429 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2430 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2431 (!is_it_true_mode && adev->native_playback_enabled)){
2432 ret = true;
2433 ALOGD("napb: time to toggle native mode");
2434 }
2435 }
2436
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302437 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302438 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2439 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002440 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302441 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302442 ALOGD("Force a2dp device switch to update new encoder config");
2443 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002444 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302445
Florian Pfister1a84f312018-07-19 14:38:18 +02002446 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302447 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2448 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002449 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302450 return ret;
2451}
2452
Aalique Grahame22e49102018-12-18 14:23:57 -08002453static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2454{
2455 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2456}
2457
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302458bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2459{
2460 bool ret=false;
2461 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002462 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2463 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302464 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2465 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002466 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002468 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2469 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302470 ret = true;
2471
2472 return ret;
2473}
2474
2475bool is_a2dp_device(snd_device_t out_snd_device)
2476{
2477 bool ret=false;
2478 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2479 ret = true;
2480
2481 return ret;
2482}
2483
2484bool is_bt_soc_on(struct audio_device *adev)
2485{
2486 struct mixer_ctl *ctl;
2487 char *mixer_ctl_name = "BT SOC status";
2488 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2489 bool bt_soc_status = true;
2490 if (!ctl) {
2491 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2492 __func__, mixer_ctl_name);
2493 /*This is to ensure we dont break targets which dont have the kernel change*/
2494 return true;
2495 }
2496 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2497 ALOGD("BT SOC status: %d",bt_soc_status);
2498 return bt_soc_status;
2499}
2500
Zhou Song331c8e52019-08-26 14:16:12 +08002501static int configure_btsco_sample_rate(snd_device_t snd_device)
2502{
2503 struct mixer_ctl *ctl = NULL;
2504 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2505 char *rate_str = NULL;
2506 bool is_rx_dev = true;
2507
2508 if (is_btsco_device(snd_device, snd_device)) {
2509 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2510 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2511 if (!ctl_sr_tx || !ctl_sr_rx) {
2512 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2513 if (!ctl_sr)
2514 return -ENOSYS;
2515 }
2516
2517 switch (snd_device) {
2518 case SND_DEVICE_OUT_BT_SCO:
2519 rate_str = "KHZ_8";
2520 break;
2521 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2522 case SND_DEVICE_IN_BT_SCO_MIC:
2523 rate_str = "KHZ_8";
2524 is_rx_dev = false;
2525 break;
2526 case SND_DEVICE_OUT_BT_SCO_WB:
2527 rate_str = "KHZ_16";
2528 break;
2529 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2530 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2531 rate_str = "KHZ_16";
2532 is_rx_dev = false;
2533 break;
2534 default:
2535 return 0;
2536 }
2537
2538 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2539 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2540 return -ENOSYS;
2541 }
2542 return 0;
2543}
2544
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302545int out_standby_l(struct audio_stream *stream);
2546
Eric Laurent637e2d42018-11-15 12:24:31 -08002547struct stream_in *adev_get_active_input(const struct audio_device *adev)
2548{
2549 struct listnode *node;
2550 struct stream_in *last_active_in = NULL;
2551
2552 /* Get last added active input.
2553 * TODO: We may use a priority mechanism to pick highest priority active source */
2554 list_for_each(node, &adev->usecase_list)
2555 {
2556 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2557 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2558 last_active_in = usecase->stream.in;
2559 }
2560
2561 return last_active_in;
2562}
2563
2564struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2565{
2566 struct listnode *node;
2567
2568 /* First check active inputs with voice communication source and then
2569 * any input if audio mode is in communication */
2570 list_for_each(node, &adev->usecase_list)
2571 {
2572 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2573 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2574 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2575 return usecase->stream.in;
2576 }
2577 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2578 return adev_get_active_input(adev);
2579
2580 return NULL;
2581}
2582
Carter Hsu2e429db2019-05-14 18:50:52 +08002583/*
2584 * Aligned with policy.h
2585 */
2586static inline int source_priority(int inputSource)
2587{
2588 switch (inputSource) {
2589 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2590 return 9;
2591 case AUDIO_SOURCE_CAMCORDER:
2592 return 8;
2593 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2594 return 7;
2595 case AUDIO_SOURCE_UNPROCESSED:
2596 return 6;
2597 case AUDIO_SOURCE_MIC:
2598 return 5;
2599 case AUDIO_SOURCE_ECHO_REFERENCE:
2600 return 4;
2601 case AUDIO_SOURCE_FM_TUNER:
2602 return 3;
2603 case AUDIO_SOURCE_VOICE_RECOGNITION:
2604 return 2;
2605 case AUDIO_SOURCE_HOTWORD:
2606 return 1;
2607 default:
2608 break;
2609 }
2610 return 0;
2611}
2612
2613static struct stream_in *get_priority_input(struct audio_device *adev)
2614{
2615 struct listnode *node;
2616 struct audio_usecase *usecase;
2617 int last_priority = 0, priority;
2618 struct stream_in *priority_in = NULL;
2619 struct stream_in *in;
2620
2621 list_for_each(node, &adev->usecase_list) {
2622 usecase = node_to_item(node, struct audio_usecase, list);
2623 if (usecase->type == PCM_CAPTURE) {
2624 in = usecase->stream.in;
2625 if (!in)
2626 continue;
2627 priority = source_priority(in->source);
2628
2629 if (priority > last_priority) {
2630 last_priority = priority;
2631 priority_in = in;
2632 }
2633 }
2634 }
2635 return priority_in;
2636}
2637
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002638int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002640 snd_device_t out_snd_device = SND_DEVICE_NONE;
2641 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642 struct audio_usecase *usecase = NULL;
2643 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002644 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002645 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302646 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002647 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002648 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302650 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002652 usecase = get_usecase_from_list(adev, uc_id);
2653 if (usecase == NULL) {
2654 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2655 return -EINVAL;
2656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002658 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002659 (usecase->type == VOIP_CALL) ||
2660 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302661 if(usecase->stream.out == NULL) {
2662 ALOGE("%s: stream.out is NULL", __func__);
2663 return -EINVAL;
2664 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002665 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002666 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2667 uc_id);
2668 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2669 uc_id);
2670 } else {
2671 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302672 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002673 in_snd_device = platform_get_input_snd_device(adev->platform,
2674 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302675 &usecase->stream.out->device_list,
2676 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002677 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002678 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302679 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302680 if (usecase->stream.inout == NULL) {
2681 ALOGE("%s: stream.inout is NULL", __func__);
2682 return -EINVAL;
2683 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002684 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302685 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2686 stream_out.format = usecase->stream.inout->out_config.format;
2687 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302688 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002689 assign_devices(&usecase->device_list,
2690 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302691 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2692 if (usecase->stream.inout == NULL) {
2693 ALOGE("%s: stream.inout is NULL", __func__);
2694 return -EINVAL;
2695 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302696 struct listnode out_devices;
2697 list_init(&out_devices);
2698 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2699 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002700 assign_devices(&usecase->device_list,
2701 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 } else {
2703 /*
2704 * If the voice call is active, use the sound devices of voice call usecase
2705 * so that it would not result any device switch. All the usecases will
2706 * be switched to new device when select_devices() is called for voice call
2707 * usecase. This is to avoid switching devices for voice call when
2708 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002709 * choose voice call device only if the use case device is
2710 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002712 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002713 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002714 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002715 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2716 is_codec_backend_out_device_type(&usecase->device_list)) ||
2717 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2718 is_codec_backend_in_device_type(&usecase->device_list)) ||
2719 is_single_device_type_equal(&vc_usecase->device_list,
2720 AUDIO_DEVICE_OUT_HEARING_AID) ||
2721 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002722 AUDIO_DEVICE_IN_VOICE_CALL) ||
2723 (is_single_device_type_equal(&usecase->device_list,
2724 AUDIO_DEVICE_IN_USB_HEADSET) &&
2725 is_single_device_type_equal(&vc_usecase->device_list,
2726 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 in_snd_device = vc_usecase->in_snd_device;
2728 out_snd_device = vc_usecase->out_snd_device;
2729 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002730 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002731 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002732 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002733 if ((voip_usecase != NULL) &&
2734 (usecase->type == PCM_PLAYBACK) &&
2735 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002736 out_snd_device_backend_match = platform_check_backends_match(
2737 voip_usecase->out_snd_device,
2738 platform_get_output_snd_device(
2739 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302740 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002741 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002742 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2743 (is_codec_backend_out_device_type(&usecase->device_list) ||
2744 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002745 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002746 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002747 in_snd_device = voip_usecase->in_snd_device;
2748 out_snd_device = voip_usecase->out_snd_device;
2749 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002750 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002751 hfp_ucid = audio_extn_hfp_get_usecase();
2752 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002753 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002754 in_snd_device = hfp_usecase->in_snd_device;
2755 out_snd_device = hfp_usecase->out_snd_device;
2756 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002757 }
2758 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302759 if (usecase->stream.out == NULL) {
2760 ALOGE("%s: stream.out is NULL", __func__);
2761 return -EINVAL;
2762 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002763 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002765 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002766 struct stream_out *voip_out = adev->primary_output;
2767 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002768 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002769 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2770 else
2771 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 usecase->stream.out,
2773 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002774 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002775
Eric Laurent637e2d42018-11-15 12:24:31 -08002776 if (voip_usecase)
2777 voip_out = voip_usecase->stream.out;
2778
2779 if (usecase->stream.out == voip_out && voip_in != NULL)
2780 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002782 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302783 if (usecase->stream.in == NULL) {
2784 ALOGE("%s: stream.in is NULL", __func__);
2785 return -EINVAL;
2786 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002787 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002788 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002789 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002791 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002792 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002793
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002794 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002795 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002796 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2797 USECASE_AUDIO_PLAYBACK_VOIP);
2798
Carter Hsu2e429db2019-05-14 18:50:52 +08002799 usecase->stream.in->enable_ec_port = false;
2800
Zhou Song62ea0282020-03-22 19:53:01 +08002801 bool is_ha_usecase = adev->ha_proxy_enable ?
2802 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2803 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2804 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002805 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002806 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002808 } else if (adev->primary_output &&
2809 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002810 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002811 } else {
2812 /* forcing speaker o/p device to get matching i/p pair
2813 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002816 priority_in = voip_in;
2817 } else {
2818 /* get the input with the highest priority source*/
2819 priority_in = get_priority_input(adev);
2820
2821 if (!priority_in)
2822 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002823 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002824
Eric Laurent637e2d42018-11-15 12:24:31 -08002825 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002826 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302827 &out_devices,
2828 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002830 }
2831 }
2832
2833 if (out_snd_device == usecase->out_snd_device &&
2834 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302835
2836 if (!force_device_switch(usecase))
2837 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
2839
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002840 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002841 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002842 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002843 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2844 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302845 }
2846
Aalique Grahame22e49102018-12-18 14:23:57 -08002847 if (out_snd_device != SND_DEVICE_NONE &&
2848 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2849 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2850 __func__,
2851 use_case_table[uc_id],
2852 adev->last_logged_snd_device[uc_id][0],
2853 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2854 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2855 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2856 -1,
2857 out_snd_device,
2858 platform_get_snd_device_name(out_snd_device),
2859 platform_get_snd_device_acdb_id(out_snd_device));
2860 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2861 }
2862 if (in_snd_device != SND_DEVICE_NONE &&
2863 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2864 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2865 __func__,
2866 use_case_table[uc_id],
2867 adev->last_logged_snd_device[uc_id][1],
2868 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2869 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2870 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2871 -1,
2872 in_snd_device,
2873 platform_get_snd_device_name(in_snd_device),
2874 platform_get_snd_device_acdb_id(in_snd_device));
2875 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2876 }
2877
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 /*
2880 * Limitation: While in call, to do a device switch we need to disable
2881 * and enable both RX and TX devices though one of them is same as current
2882 * device.
2883 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002884 if ((usecase->type == VOICE_CALL) &&
2885 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2886 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002887 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002888 }
2889
2890 if (((usecase->type == VOICE_CALL) ||
2891 (usecase->type == VOIP_CALL)) &&
2892 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2893 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302894 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002895 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002896 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002897
2898 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302899 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002900 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002901 }
2902
Aalique Grahame22e49102018-12-18 14:23:57 -08002903 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2904 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002905 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302906 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002907 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2908 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2909 else
2910 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302911 }
2912
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002913 /* Disable current sound devices */
2914 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002915 disable_audio_route(adev, usecase);
2916 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 }
2918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002919 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002920 disable_audio_route(adev, usecase);
2921 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 }
2923
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002924 /* Applicable only on the targets that has external modem.
2925 * New device information should be sent to modem before enabling
2926 * the devices to reduce in-call device switch time.
2927 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002928 if ((usecase->type == VOICE_CALL) &&
2929 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2930 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002931 status = platform_switch_voice_call_enable_device_config(adev->platform,
2932 out_snd_device,
2933 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002934 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 /* Enable new sound devices */
2937 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002938 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302939 if (platform_check_codec_asrc_support(adev->platform))
2940 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002941 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002944 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302945 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002946 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002948
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302949 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07002950 status = platform_switch_voice_call_device_post(adev->platform,
2951 out_snd_device,
2952 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002953
sangwoo170731f2013-06-08 15:36:36 +09002954 usecase->in_snd_device = in_snd_device;
2955 usecase->out_snd_device = out_snd_device;
2956
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302957 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2958 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302959 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002960 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002961 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002962 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2963 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2964 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2965 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2966 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2967 /*
2968 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2969 * configured device sample rate, if not update the COPP rate to be equal to the
2970 * device sample rate, else open COPP at stream sample rate
2971 */
2972 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2973 usecase->stream.out->sample_rate,
2974 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302975 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302976 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2977 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302978 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002979 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2980 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2981 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2982 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002983 }
2984 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002985
Shalini Manjunatha8ae54892020-12-29 13:02:25 +05302986 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
2987 struct stream_in *voip_in = get_voice_communication_input(adev);
2988 struct audio_usecase *voip_in_usecase = NULL;
2989 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
2990 if (voip_in != NULL &&
2991 voip_in_usecase != NULL &&
2992 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
2993 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
2994 (voip_in_usecase->in_snd_device ==
2995 platform_get_input_snd_device(adev->platform, voip_in,
2996 &usecase->stream.out->device_list,usecase->type))) {
2997 /*
2998 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
2999 * for enabling echo-reference-voip with correct port
3000 */
3001 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3002 disable_audio_route(adev, voip_in_usecase);
3003 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3004 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3005 enable_audio_route(adev, voip_in_usecase);
3006 }
3007 }
3008
3009
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003010 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003011
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003012 /* If input stream is already running then effect needs to be
3013 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003014 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003015 check_and_enable_effect(adev);
3016
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003017 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003018 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303019 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003020 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3021
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003022 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303023 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003024 voice_extn_compress_voip_is_started(adev))
3025 voice_set_sidetone(adev, out_snd_device, true);
3026 }
3027
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003028 /* Applicable only on the targets that has external modem.
3029 * Enable device command should be sent to modem only after
3030 * enabling voice call mixer controls
3031 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003032 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003033 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3034 out_snd_device,
3035 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303036
3037 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003038 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303039 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003040 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303041 if (is_bt_soc_on(adev) == false){
3042 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003043 if (in->pcm != NULL)
3044 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303045 }
3046 }
3047 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3048 && usecase->stream.out->started) {
3049 if (is_bt_soc_on(adev) == false) {
3050 ALOGD("BT SCO/A2DP disconnected while in connection");
3051 out_standby_l(&usecase->stream.out->stream.common);
3052 }
3053 }
3054 } else if ((usecase->stream.out != NULL) &&
3055 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303056 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3057 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003058 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303059 usecase->stream.out->started) {
3060 if (is_bt_soc_on(adev) == false) {
3061 ALOGD("BT SCO/A2dp disconnected while in connection");
3062 out_standby_l(&usecase->stream.out->stream.common);
3063 }
3064 }
3065 }
3066
Yung Ti Su70cb8242018-06-22 17:38:47 +08003067 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003068 struct stream_out *voip_out = voip_usecase->stream.out;
3069 audio_extn_utils_send_app_type_gain(adev,
3070 voip_out->app_type_cfg.app_type,
3071 &voip_out->app_type_cfg.gain[0]);
3072 }
3073
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303074 ALOGD("%s: done",__func__);
3075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 return status;
3077}
3078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079static int stop_input_stream(struct stream_in *in)
3080{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303081 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303083
3084 if (in == NULL) {
3085 ALOGE("%s: stream_in ptr is NULL", __func__);
3086 return -EINVAL;
3087 }
3088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003090 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091
Eric Laurent994a6932013-07-17 11:51:42 -07003092 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003093 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 uc_info = get_usecase_from_list(adev, in->usecase);
3095 if (uc_info == NULL) {
3096 ALOGE("%s: Could not find the usecase (%d) in the list",
3097 __func__, in->usecase);
3098 return -EINVAL;
3099 }
3100
Carter Hsu2e429db2019-05-14 18:50:52 +08003101 priority_in = get_priority_input(adev);
3102
Derek Chenea197282019-01-07 17:35:01 -08003103 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3104 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003105
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003106 /* Close in-call recording streams */
3107 voice_check_and_stop_incall_rec_usecase(adev, in);
3108
Eric Laurent150dbfe2013-02-27 14:31:02 -08003109 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003110 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003111
3112 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003113 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003115 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303116 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3117
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003118 list_remove(&uc_info->list);
3119 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120
Carter Hsu2e429db2019-05-14 18:50:52 +08003121 if (priority_in == in) {
3122 priority_in = get_priority_input(adev);
3123 if (priority_in)
3124 select_devices(adev, priority_in->usecase);
3125 }
3126
Vatsal Buchac09ae062018-11-14 13:25:08 +05303127 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003128 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 return ret;
3130}
3131
3132int start_input_stream(struct stream_in *in)
3133{
3134 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003135 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303137
3138 if (in == NULL) {
3139 ALOGE("%s: stream_in ptr is NULL", __func__);
3140 return -EINVAL;
3141 }
3142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003144 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003145 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Mingming Yin2664a5b2015-09-03 10:53:11 -07003147 if (get_usecase_from_list(adev, usecase) == NULL)
3148 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303149 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3150 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003151
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303152 if (CARD_STATUS_OFFLINE == in->card_status||
3153 CARD_STATUS_OFFLINE == adev->card_status) {
3154 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303155 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303156 goto error_config;
3157 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003159 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303160 if (!adev->bt_sco_on) {
3161 ALOGE("%s: SCO profile is not ready, return error", __func__);
3162 ret = -EIO;
3163 goto error_config;
3164 }
3165 }
3166
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003167 /* Check if source matches incall recording usecase criteria */
3168 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3169 if (ret)
3170 goto error_config;
3171 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003172 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3173
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303174 if (audio_extn_cin_attached_usecase(in))
3175 audio_extn_cin_acquire_usecase(in);
3176
Mingming Yin2664a5b2015-09-03 10:53:11 -07003177 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3178 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3179 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003180 ret = -EINVAL;
3181 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003182 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003183
Eric Laurentb23d5282013-05-14 15:27:20 -07003184 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (in->pcm_device_id < 0) {
3186 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3187 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003188 ret = -EINVAL;
3189 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003193
3194 if (!uc_info) {
3195 ret = -ENOMEM;
3196 goto error_config;
3197 }
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 uc_info->id = in->usecase;
3200 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003201 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003202 list_init(&uc_info->device_list);
3203 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003204 uc_info->in_snd_device = SND_DEVICE_NONE;
3205 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003207 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003208 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303209 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3210 adev->perf_lock_opts,
3211 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003212 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213
Derek Chenea197282019-01-07 17:35:01 -08003214 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3215 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003216
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303217 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3218
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303219 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303220 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303221 if (ret)
3222 goto error_open;
3223 else
3224 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 }
3226
Haynes Mathew George16081042017-05-31 17:16:49 -07003227 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 ALOGE("%s: pcm stream not ready", __func__);
3230 goto error_open;
3231 }
3232 ret = pcm_start(in->pcm);
3233 if (ret < 0) {
3234 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3235 goto error_open;
3236 }
3237 } else {
3238 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3239 unsigned int pcm_open_retry_count = 0;
3240
Zhou Song62ea0282020-03-22 19:53:01 +08003241 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3242 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003243 flags |= PCM_MMAP | PCM_NOIRQ;
3244 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3245 } else if (in->realtime) {
3246 flags |= PCM_MMAP | PCM_NOIRQ;
3247 }
3248
Garmond Leunge2433c32017-09-28 21:51:22 -07003249 if (audio_extn_ffv_get_stream() == in) {
3250 ALOGD("%s: ffv stream, update pcm config", __func__);
3251 audio_extn_ffv_update_pcm_config(&config);
3252 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3254 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3255
3256 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003257 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003258 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003259 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303261 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303262 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3263 adev->card_status = CARD_STATUS_OFFLINE;
3264 in->card_status = CARD_STATUS_OFFLINE;
3265 ret = -EIO;
3266 goto error_open;
3267 }
3268
Haynes Mathew George16081042017-05-31 17:16:49 -07003269 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3270 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3271 if (in->pcm != NULL) {
3272 pcm_close(in->pcm);
3273 in->pcm = NULL;
3274 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003275 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 ret = -EIO;
3277 goto error_open;
3278 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003279 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003280 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3281 continue;
3282 }
3283 break;
3284 }
3285
3286 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003287 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003288 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003289 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003290 if (ret < 0) {
3291 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3292 pcm_close(in->pcm);
3293 in->pcm = NULL;
3294 goto error_open;
3295 }
3296 register_in_stream(in);
3297 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003298 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003299 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003300 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003301 if (ret < 0) {
3302 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003303 pcm_close(in->pcm);
3304 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003305 goto error_open;
3306 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003307 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003308 }
3309
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003310 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003311 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3312 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003313
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003314 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303315 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3316
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303317done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003318 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303319 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003320 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303321 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003322 return ret;
3323
3324error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003325 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303326 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003328
Eric Laurentc8400632013-02-14 19:04:54 -08003329error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003330 if (audio_extn_cin_attached_usecase(in))
3331 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303332 /*
3333 * sleep 50ms to allow sufficient time for kernel
3334 * drivers to recover incases like SSR.
3335 */
3336 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003337 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303338 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340}
3341
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003342void lock_input_stream(struct stream_in *in)
3343{
3344 pthread_mutex_lock(&in->pre_lock);
3345 pthread_mutex_lock(&in->lock);
3346 pthread_mutex_unlock(&in->pre_lock);
3347}
3348
3349void lock_output_stream(struct stream_out *out)
3350{
3351 pthread_mutex_lock(&out->pre_lock);
3352 pthread_mutex_lock(&out->lock);
3353 pthread_mutex_unlock(&out->pre_lock);
3354}
3355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356/* must be called with out->lock locked */
3357static int send_offload_cmd_l(struct stream_out* out, int command)
3358{
3359 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3360
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003361 if (!cmd) {
3362 ALOGE("failed to allocate mem for command 0x%x", command);
3363 return -ENOMEM;
3364 }
3365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 ALOGVV("%s %d", __func__, command);
3367
3368 cmd->cmd = command;
3369 list_add_tail(&out->offload_cmd_list, &cmd->node);
3370 pthread_cond_signal(&out->offload_cond);
3371 return 0;
3372}
3373
Gautam Manamfeeb1162020-12-24 14:08:04 +05303374/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375static void stop_compressed_output_l(struct stream_out *out)
3376{
Gautam Manamfeeb1162020-12-24 14:08:04 +05303377 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manamfeeb1162020-12-24 14:08:04 +05303379 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003381 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382 if (out->compr != NULL) {
3383 compress_stop(out->compr);
3384 while (out->offload_thread_blocked) {
3385 pthread_cond_wait(&out->cond, &out->lock);
3386 }
3387 }
3388}
3389
Varun Balaraje49253e2017-07-06 19:48:56 +05303390bool is_interactive_usecase(audio_usecase_t uc_id)
3391{
3392 unsigned int i;
3393 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3394 if (uc_id == interactive_usecases[i])
3395 return true;
3396 }
3397 return false;
3398}
3399
3400static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3401{
3402 audio_usecase_t ret_uc = USECASE_INVALID;
3403 unsigned int intract_uc_index;
3404 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3405
3406 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3407 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3408 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3409 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3410 ret_uc = interactive_usecases[intract_uc_index];
3411 break;
3412 }
3413 }
3414
3415 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3416 return ret_uc;
3417}
3418
3419static void free_interactive_usecase(struct audio_device *adev,
3420 audio_usecase_t uc_id)
3421{
3422 unsigned int interact_uc_index;
3423 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3424
3425 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3426 if (interactive_usecases[interact_uc_index] == uc_id) {
3427 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3428 break;
3429 }
3430 }
3431 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3432}
3433
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003434bool is_offload_usecase(audio_usecase_t uc_id)
3435{
3436 unsigned int i;
3437 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3438 if (uc_id == offload_usecases[i])
3439 return true;
3440 }
3441 return false;
3442}
3443
Dhananjay Kumarac341582017-02-23 23:42:25 +05303444static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003445{
vivek mehta446c3962015-09-14 10:57:35 -07003446 audio_usecase_t ret_uc = USECASE_INVALID;
3447 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003448 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003449 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303450 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003451 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3452 else
3453 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003454
vivek mehta446c3962015-09-14 10:57:35 -07003455 pthread_mutex_lock(&adev->lock);
3456 if (get_usecase_from_list(adev, ret_uc) != NULL)
3457 ret_uc = USECASE_INVALID;
3458 pthread_mutex_unlock(&adev->lock);
3459
3460 return ret_uc;
3461 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003462
3463 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003464 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3465 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3466 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3467 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003468 break;
3469 }
3470 }
vivek mehta446c3962015-09-14 10:57:35 -07003471
3472 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3473 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003474}
3475
3476static void free_offload_usecase(struct audio_device *adev,
3477 audio_usecase_t uc_id)
3478{
vivek mehta446c3962015-09-14 10:57:35 -07003479 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003480 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003481
3482 if (!adev->multi_offload_enable)
3483 return;
3484
3485 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3486 if (offload_usecases[offload_uc_index] == uc_id) {
3487 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003488 break;
3489 }
3490 }
3491 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3492}
3493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003494static void *offload_thread_loop(void *context)
3495{
3496 struct stream_out *out = (struct stream_out *) context;
3497 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003498 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003501 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3503
3504 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003505 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003506 out->offload_state = OFFLOAD_STATE_IDLE;
3507 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003508 for (;;) {
3509 struct offload_cmd *cmd = NULL;
3510 stream_callback_event_t event;
3511 bool send_callback = false;
3512
3513 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3514 __func__, list_empty(&out->offload_cmd_list),
3515 out->offload_state);
3516 if (list_empty(&out->offload_cmd_list)) {
3517 ALOGV("%s SLEEPING", __func__);
3518 pthread_cond_wait(&out->offload_cond, &out->lock);
3519 ALOGV("%s RUNNING", __func__);
3520 continue;
3521 }
3522
3523 item = list_head(&out->offload_cmd_list);
3524 cmd = node_to_item(item, struct offload_cmd, node);
3525 list_remove(item);
3526
3527 ALOGVV("%s STATE %d CMD %d out->compr %p",
3528 __func__, out->offload_state, cmd->cmd, out->compr);
3529
3530 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3531 free(cmd);
3532 break;
3533 }
3534
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003535 // allow OFFLOAD_CMD_ERROR reporting during standby
3536 // this is needed to handle failures during compress_open
3537 // Note however that on a pause timeout, the stream is closed
3538 // and no offload usecase will be active. Therefore this
3539 // special case is needed for compress_open failures alone
3540 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3541 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003543 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003544 pthread_cond_signal(&out->cond);
3545 continue;
3546 }
3547 out->offload_thread_blocked = true;
3548 pthread_mutex_unlock(&out->lock);
3549 send_callback = false;
3550 switch(cmd->cmd) {
3551 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003552 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003554 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 send_callback = true;
3556 event = STREAM_CBK_EVENT_WRITE_READY;
3557 break;
3558 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003559 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303560 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003561 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303562 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003563 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303564 if (ret < 0)
3565 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303566 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303567 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003568 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003569 else
3570 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003571 if (-ENETRESET != ret && !(-EINTR == ret &&
3572 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303573 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303574 pthread_mutex_lock(&out->lock);
3575 out->send_new_metadata = 1;
3576 out->send_next_track_params = true;
3577 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303578 event = STREAM_CBK_EVENT_DRAIN_READY;
3579 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3580 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303581 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 break;
3583 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003584 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003585 ret = compress_drain(out->compr);
3586 ALOGD("copl(%p):out of compress_drain", out);
3587 // EINTR check avoids drain interruption due to SSR
3588 if (-ENETRESET != ret && !(-EINTR == ret &&
3589 CARD_STATUS_OFFLINE == out->card_status)) {
3590 send_callback = true;
3591 event = STREAM_CBK_EVENT_DRAIN_READY;
3592 } else
3593 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003594 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303595 case OFFLOAD_CMD_ERROR:
3596 ALOGD("copl(%p): sending error callback to AF", out);
3597 send_callback = true;
3598 event = STREAM_CBK_EVENT_ERROR;
3599 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003600 default:
3601 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3602 break;
3603 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003604 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003605 out->offload_thread_blocked = false;
3606 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003607 if (send_callback && out->client_callback) {
3608 ALOGVV("%s: sending client_callback event %d", __func__, event);
3609 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003610 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 free(cmd);
3612 }
3613
3614 pthread_cond_signal(&out->cond);
3615 while (!list_empty(&out->offload_cmd_list)) {
3616 item = list_head(&out->offload_cmd_list);
3617 list_remove(item);
3618 free(node_to_item(item, struct offload_cmd, node));
3619 }
3620 pthread_mutex_unlock(&out->lock);
3621
3622 return NULL;
3623}
3624
3625static int create_offload_callback_thread(struct stream_out *out)
3626{
3627 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3628 list_init(&out->offload_cmd_list);
3629 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3630 offload_thread_loop, out);
3631 return 0;
3632}
3633
3634static int destroy_offload_callback_thread(struct stream_out *out)
3635{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003636 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003637 stop_compressed_output_l(out);
3638 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3639
3640 pthread_mutex_unlock(&out->lock);
3641 pthread_join(out->offload_thread, (void **) NULL);
3642 pthread_cond_destroy(&out->offload_cond);
3643
3644 return 0;
3645}
3646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647static int stop_output_stream(struct stream_out *out)
3648{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303649 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 struct audio_usecase *uc_info;
3651 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003652 bool has_voip_usecase =
3653 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654
Eric Laurent994a6932013-07-17 11:51:42 -07003655 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003656 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 uc_info = get_usecase_from_list(adev, out->usecase);
3658 if (uc_info == NULL) {
3659 ALOGE("%s: Could not find the usecase (%d) in the list",
3660 __func__, out->usecase);
3661 return -EINVAL;
3662 }
3663
Zhou Song1f93fa52020-11-20 13:57:39 +08003664 out->a2dp_muted = false;
3665
Derek Chenea197282019-01-07 17:35:01 -08003666 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3667 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003668
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003669 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303670 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003671 if (adev->visualizer_stop_output != NULL)
3672 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003673
3674 audio_extn_dts_remove_state_notifier_node(out->usecase);
3675
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003676 if (adev->offload_effects_stop_output != NULL)
3677 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003678 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3679 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3680 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003681 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003682
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003683 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3684 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003685 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003686 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003687
Eric Laurent150dbfe2013-02-27 14:31:02 -08003688 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003689 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003690
3691 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003692 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693
Aalique Grahame22e49102018-12-18 14:23:57 -08003694 audio_extn_extspk_update(adev->extspk);
3695
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003696 if (is_offload_usecase(out->usecase)) {
3697 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3698 adev->dsp_bit_width_enforce_mode,
3699 false);
3700 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003701 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003702 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3703 false);
3704
3705 if (ret != 0)
3706 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3707 /* default service interval was successfully updated,
3708 reopen USB backend with new service interval */
3709 ret = 0;
3710 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003711
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003712 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303713 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003714 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303715 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003716 ALOGV("Disable passthrough , reset mixer to pcm");
3717 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003718#ifdef AUDIO_GKI_ENABLED
3719 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3720 out->compr_config.codec->reserved[0] = 0;
3721#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003722 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003723#endif
Mingming Yin21854652016-04-13 11:54:02 -07003724 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003725 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3726 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003727
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303728 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003729 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303730 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303731
Manish Dewangan21a850a2017-08-14 12:03:55 +05303732 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003733 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3734 if (ret < 0)
3735 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3736 }
3737
juyuchen2d415992018-11-16 14:15:16 +08003738 /* 1) media + voip output routing to handset must route media back to
3739 speaker when voip stops.
3740 2) trigger voip input to reroute when voip output changes to
3741 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003742 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003743 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003744 struct listnode *node;
3745 struct audio_usecase *usecase;
3746 list_for_each(node, &adev->usecase_list) {
3747 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003748 if ((usecase->type == PCM_CAPTURE &&
3749 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3750 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003751 continue;
3752
3753 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3754 __func__, usecase->id, use_case_table[usecase->id],
3755 out->usecase, use_case_table[out->usecase]);
3756 select_devices(adev, usecase->id);
3757 }
3758 }
3759
Garmond Leung5fd0b552018-04-17 11:56:12 -07003760 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003761 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 return ret;
3763}
3764
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003765struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3766 unsigned int flags, unsigned int pcm_open_retry_count,
3767 struct pcm_config *config)
3768{
3769 struct pcm* pcm = NULL;
3770
3771 while (1) {
3772 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3773 if (pcm == NULL || !pcm_is_ready(pcm)) {
3774 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3775 if (pcm != NULL) {
3776 pcm_close(pcm);
3777 pcm = NULL;
3778 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003779 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003780 return NULL;
3781
Weiyin Jiang72197252019-10-09 11:49:32 +08003782 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003783 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3784 continue;
3785 }
3786 break;
3787 }
3788
3789 if (pcm_is_ready(pcm)) {
3790 int ret = pcm_prepare(pcm);
3791 if (ret < 0) {
3792 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3793 pcm_close(pcm);
3794 pcm = NULL;
3795 }
3796 }
3797
3798 return pcm;
3799}
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801int start_output_stream(struct stream_out *out)
3802{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 struct audio_usecase *uc_info;
3805 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003806 char mixer_ctl_name[128];
3807 struct mixer_ctl *ctl = NULL;
3808 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303809 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003810 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811
Haynes Mathew George380745d2017-10-04 15:27:45 -07003812 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003813 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3814 ret = -EINVAL;
3815 goto error_config;
3816 }
3817
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003818 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303819 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003820 get_device_types(&out->device_list), is_haptic_usecase);
3821
3822 bool is_speaker_active = compare_device_type(&out->device_list,
3823 AUDIO_DEVICE_OUT_SPEAKER);
3824 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3825 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303826
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303827 if (CARD_STATUS_OFFLINE == out->card_status ||
3828 CARD_STATUS_OFFLINE == adev->card_status) {
3829 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303830 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003831 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303832 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303833
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003834 //Update incall music usecase to reflect correct voice session
3835 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3836 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3837 if (ret != 0) {
3838 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3839 __func__, ret);
3840 goto error_config;
3841 }
3842 }
3843
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003844 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003845 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003846 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303847 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303848 } else {
Zhou Song9ebf6792020-09-23 22:49:01 +08003849 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303850 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3851 ret = -EAGAIN;
3852 goto error_config;
3853 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303854 }
3855 }
3856 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003857 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303858 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003859 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303860 //combo usecase just by pass a2dp
3861 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003862 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303863 } else {
3864 ALOGE("%s: SCO profile is not ready, return error", __func__);
3865 ret = -EAGAIN;
3866 goto error_config;
3867 }
3868 }
3869 }
3870
Eric Laurentb23d5282013-05-14 15:27:20 -07003871 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 if (out->pcm_device_id < 0) {
3873 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3874 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003875 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003876 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 }
3878
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003879 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003880 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3881 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 if (adev->haptic_pcm_device_id < 0) {
3883 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3884 __func__, adev->haptic_pcm_device_id, out->usecase);
3885 ret = -EINVAL;
3886 goto error_config;
3887 }
3888 }
3889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003891
3892 if (!uc_info) {
3893 ret = -ENOMEM;
3894 goto error_config;
3895 }
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 uc_info->id = out->usecase;
3898 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003899 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003900 list_init(&uc_info->device_list);
3901 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003902 uc_info->in_snd_device = SND_DEVICE_NONE;
3903 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003904
3905 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003906 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003907 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3908 /* USB backend is not reopened immediately.
3909 This is eventually done as part of select_devices */
3910 }
3911
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003912 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913
Wei Wangf7ca6c92017-11-21 14:51:20 -08003914 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303915 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3916 adev->perf_lock_opts,
3917 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303918
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003919 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303920 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303921 if (audio_extn_passthru_is_enabled() &&
3922 audio_extn_passthru_is_passthrough_stream(out)) {
3923 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303924 }
3925 }
3926
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003927 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003928 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303929 if (!a2dp_combo) {
3930 check_a2dp_restore_l(adev, out, false);
3931 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003932 struct listnode dev;
3933 list_init(&dev);
3934 assign_devices(&dev, &out->device_list);
3935 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3936 reassign_device_list(&out->device_list,
3937 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003938 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003939 reassign_device_list(&out->device_list,
3940 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303941 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003942 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303943 }
3944 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303945 select_devices(adev, out->usecase);
3946 if (is_a2dp_out_device_type(&out->device_list) &&
3947 !adev->a2dp_started) {
3948 if (is_speaker_active || is_speaker_safe_active) {
3949 struct listnode dev;
3950 list_init(&dev);
3951 assign_devices(&dev, &out->device_list);
3952 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3953 reassign_device_list(&out->device_list,
3954 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3955 else
3956 reassign_device_list(&out->device_list,
3957 AUDIO_DEVICE_OUT_SPEAKER, "");
3958 select_devices(adev, out->usecase);
3959 assign_devices(&out->device_list, &dev);
3960 } else {
3961 ret = -EINVAL;
3962 goto error_open;
3963 }
3964 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303965 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003966
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003967 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3968 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003969 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003970 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003971
Derek Chenea197282019-01-07 17:35:01 -08003972 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3973 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003974
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003975 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3976 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003977
3978 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003979 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003980 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3981 ALOGE("%s: pcm stream not ready", __func__);
3982 goto error_open;
3983 }
3984 ret = pcm_start(out->pcm);
3985 if (ret < 0) {
3986 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3987 goto error_open;
3988 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003989 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003990 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003991 unsigned int flags = PCM_OUT;
3992 unsigned int pcm_open_retry_count = 0;
3993 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3994 flags |= PCM_MMAP | PCM_NOIRQ;
3995 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003996 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003997 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003998 } else
3999 flags |= PCM_MONOTONIC;
4000
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004001 if ((adev->vr_audio_mode_enabled) &&
4002 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4003 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4004 "PCM_Dev %d Topology", out->pcm_device_id);
4005 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4006 if (!ctl) {
4007 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4008 __func__, mixer_ctl_name);
4009 } else {
4010 //if success use ULLPP
4011 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4012 __func__, mixer_ctl_name, out->pcm_device_id);
4013 //There is a still a possibility that some sessions
4014 // that request for FAST|RAW when 3D audio is active
4015 //can go through ULLPP. Ideally we expects apps to
4016 //listen to audio focus and stop concurrent playback
4017 //Also, we will look for mode flag (voice_in_communication)
4018 //before enabling the realtime flag.
4019 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4020 }
4021 }
4022
Surendar Karka91fa3682018-07-02 18:12:12 +05304023 if (out->realtime)
4024 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4025 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4026
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004027 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4028 flags, pcm_open_retry_count,
4029 &(out->config));
4030 if (out->pcm == NULL) {
4031 ret = -EIO;
4032 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004033 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004034
4035 if (is_haptic_usecase) {
4036 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4037 adev->haptic_pcm_device_id,
4038 flags, pcm_open_retry_count,
4039 &(adev->haptics_config));
4040 // failure to open haptics pcm shouldnt stop audio,
4041 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004042
4043 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4044 ALOGD("%s: enable haptic audio synchronization", __func__);
4045 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4046 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004047 }
4048
Surendar Karka91fa3682018-07-02 18:12:12 +05304049 if (!out->realtime)
4050 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304051 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004052
Zhou Song2b8f28f2017-09-11 10:51:38 +08004053 // apply volume for voip playback after path is set up
4054 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4055 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304056 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4057 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304058 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4059 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004060 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4061 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304062 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004063 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004064 /*
4065 * set custom channel map if:
4066 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4067 * 2. custom channel map has been set by client
4068 * else default channel map of FC/FR/FL can always be set to DSP
4069 */
4070 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4071 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4072 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004073 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4074 adev->dsp_bit_width_enforce_mode,
4075 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004077 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004078 out->compr = compress_open(adev->snd_card,
4079 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004080 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004081 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304082 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304083 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4084 adev->card_status = CARD_STATUS_OFFLINE;
4085 out->card_status = CARD_STATUS_OFFLINE;
4086 ret = -EIO;
4087 goto error_open;
4088 }
4089
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004090 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004091 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004092 compress_close(out->compr);
4093 out->compr = NULL;
4094 ret = -EIO;
4095 goto error_open;
4096 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304097 /* compress_open sends params of the track, so reset the flag here */
4098 out->is_compr_metadata_avail = false;
4099
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004100 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004102
Fred Oh3f43e742015-03-04 18:42:34 -08004103 /* Since small bufs uses blocking writes, a write will be blocked
4104 for the default max poll time (20s) in the event of an SSR.
4105 Reduce the poll time to observe and deal with SSR faster.
4106 */
Ashish Jain5106d362016-05-11 19:23:33 +05304107 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004108 compress_set_max_poll_wait(out->compr, 1000);
4109 }
4110
Manish Dewangan69426c82017-01-30 17:35:36 +05304111 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304112 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304113
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004114 audio_extn_dts_create_state_notifier_node(out->usecase);
4115 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4116 popcount(out->channel_mask),
4117 out->playback_started);
4118
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004119#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304120 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004121 audio_extn_dolby_send_ddp_endp_params(adev);
4122#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304123 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4124 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004125 if (adev->visualizer_start_output != NULL)
4126 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4127 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304128 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004129 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004130 }
Derek Chenf13dd492018-11-13 14:53:51 -08004131
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004132 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004133 /* Update cached volume from media to offload/direct stream */
4134 struct listnode *node = NULL;
4135 list_for_each(node, &adev->active_outputs_list) {
4136 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4137 streams_output_ctxt_t,
4138 list);
4139 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4140 out->volume_l = out_ctxt->output->volume_l;
4141 out->volume_r = out_ctxt->output->volume_r;
4142 }
4143 }
4144 out_set_compr_volume(&out->stream,
4145 out->volume_l, out->volume_r);
4146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004148
4149 if (ret == 0) {
4150 register_out_stream(out);
4151 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004152 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4153 ALOGE("%s: pcm stream not ready", __func__);
4154 goto error_open;
4155 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004156 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004157 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004158 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004159 if (ret < 0)
4160 goto error_open;
4161 }
4162 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004163 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304164 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004165 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004166
vivek mehtad15d2bf2019-05-17 13:35:10 -07004167 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4168 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4169 audio_low_latency_hint_start();
4170 }
4171
Manish Dewangan21a850a2017-08-14 12:03:55 +05304172 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004173 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004174 if (ret < 0)
4175 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4176 }
4177
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004178 // consider a scenario where on pause lower layers are tear down.
4179 // so on resume, swap mixer control need to be sent only when
4180 // backend is active, hence rather than sending from enable device
4181 // sending it from start of streamtream
4182
4183 platform_set_swap_channels(adev, true);
4184
Haynes Mathew George380745d2017-10-04 15:27:45 -07004185 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304186 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004187 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004188error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004189 if (adev->haptic_pcm) {
4190 pcm_close(adev->haptic_pcm);
4191 adev->haptic_pcm = NULL;
4192 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004193 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304194 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004196error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304197 /*
4198 * sleep 50ms to allow sufficient time for kernel
4199 * drivers to recover incases like SSR.
4200 */
4201 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004202error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004203 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304204 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206}
4207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208static int check_input_parameters(uint32_t sample_rate,
4209 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004210 int channel_count,
4211 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004213 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304215 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4216 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4217 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004218 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004219 !audio_extn_compr_cap_format_supported(format) &&
4220 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004221 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004222
Aalique Grahame22e49102018-12-18 14:23:57 -08004223 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4224 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4225 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4226 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4227 return -EINVAL;
4228 }
4229
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004230 switch (channel_count) {
4231 case 1:
4232 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304233 case 3:
4234 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004235 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004236 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304237 case 10:
4238 case 12:
4239 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004240 break;
4241 default:
4242 ret = -EINVAL;
4243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244
4245 switch (sample_rate) {
4246 case 8000:
4247 case 11025:
4248 case 12000:
4249 case 16000:
4250 case 22050:
4251 case 24000:
4252 case 32000:
4253 case 44100:
4254 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004255 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304256 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004257 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304258 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 break;
4260 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004261 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 }
4263
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265}
4266
Naresh Tanniru04f71882018-06-26 17:46:22 +05304267
4268/** Add a value in a list if not already present.
4269 * @return true if value was successfully inserted or already present,
4270 * false if the list is full and does not contain the value.
4271 */
4272static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4273 for (size_t i = 0; i < list_length; i++) {
4274 if (list[i] == value) return true; // value is already present
4275 if (list[i] == 0) { // no values in this slot
4276 list[i] = value;
4277 return true; // value inserted
4278 }
4279 }
4280 return false; // could not insert value
4281}
4282
4283/** Add channel_mask in supported_channel_masks if not already present.
4284 * @return true if channel_mask was successfully inserted or already present,
4285 * false if supported_channel_masks is full and does not contain channel_mask.
4286 */
4287static void register_channel_mask(audio_channel_mask_t channel_mask,
4288 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4289 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4290 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4291}
4292
4293/** Add format in supported_formats if not already present.
4294 * @return true if format was successfully inserted or already present,
4295 * false if supported_formats is full and does not contain format.
4296 */
4297static void register_format(audio_format_t format,
4298 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4299 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4300 "%s: stream can not declare supporting its format %x", __func__, format);
4301}
4302/** Add sample_rate in supported_sample_rates if not already present.
4303 * @return true if sample_rate was successfully inserted or already present,
4304 * false if supported_sample_rates is full and does not contain sample_rate.
4305 */
4306static void register_sample_rate(uint32_t sample_rate,
4307 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4308 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4309 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4310}
4311
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004312static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4313{
4314 uint32_t high = num1, low = num2, temp = 0;
4315
4316 if (!num1 || !num2)
4317 return 0;
4318
4319 if (num1 < num2) {
4320 high = num2;
4321 low = num1;
4322 }
4323
4324 while (low != 0) {
4325 temp = low;
4326 low = high % low;
4327 high = temp;
4328 }
4329 return (num1 * num2)/high;
4330}
4331
4332static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4333{
4334 uint32_t remainder = 0;
4335
4336 if (!multiplier)
4337 return num;
4338
4339 remainder = num % multiplier;
4340 if (remainder)
4341 num += (multiplier - remainder);
4342
4343 return num;
4344}
4345
Aalique Grahame22e49102018-12-18 14:23:57 -08004346static size_t get_stream_buffer_size(size_t duration_ms,
4347 uint32_t sample_rate,
4348 audio_format_t format,
4349 int channel_count,
4350 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351{
4352 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004353 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354
Aalique Grahame22e49102018-12-18 14:23:57 -08004355 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004356 if (is_low_latency)
4357 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304358
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004359 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004360 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361
Ralf Herzbd08d632018-09-28 15:50:49 +02004362 /* make sure the size is multiple of 32 bytes and additionally multiple of
4363 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004364 * At 48 kHz mono 16-bit PCM:
4365 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4366 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004367 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004368 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004369 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004370
4371 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372}
4373
Aalique Grahame22e49102018-12-18 14:23:57 -08004374static size_t get_input_buffer_size(uint32_t sample_rate,
4375 audio_format_t format,
4376 int channel_count,
4377 bool is_low_latency)
4378{
4379 /* Don't know if USB HIFI in this context so use true to be conservative */
4380 if (check_input_parameters(sample_rate, format, channel_count,
4381 true /*is_usb_hifi */) != 0)
4382 return 0;
4383
4384 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4385 sample_rate,
4386 format,
4387 channel_count,
4388 is_low_latency);
4389}
4390
Derek Chenf6318be2017-06-12 17:16:24 -04004391size_t get_output_period_size(uint32_t sample_rate,
4392 audio_format_t format,
4393 int channel_count,
4394 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304395{
4396 size_t size = 0;
4397 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4398
4399 if ((duration == 0) || (sample_rate == 0) ||
4400 (bytes_per_sample == 0) || (channel_count == 0)) {
4401 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4402 bytes_per_sample, channel_count);
4403 return -EINVAL;
4404 }
4405
4406 size = (sample_rate *
4407 duration *
4408 bytes_per_sample *
4409 channel_count) / 1000;
4410 /*
4411 * To have same PCM samples for all channels, the buffer size requires to
4412 * be multiple of (number of channels * bytes per sample)
4413 * For writes to succeed, the buffer must be written at address which is multiple of 32
4414 */
4415 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4416
4417 return (size/(channel_count * bytes_per_sample));
4418}
4419
Zhou Song48453a02018-01-10 17:50:59 +08004420static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304421{
4422 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004423 uint64_t written_frames = 0;
4424 uint64_t kernel_frames = 0;
4425 uint64_t dsp_frames = 0;
4426 uint64_t signed_frames = 0;
4427 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304428
4429 /* This adjustment accounts for buffering after app processor.
4430 * It is based on estimated DSP latency per use case, rather than exact.
4431 */
George Gao9ba8a142020-07-23 14:30:03 -07004432 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004433 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304434
Zhou Song48453a02018-01-10 17:50:59 +08004435 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004436 written_frames = out->written /
4437 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4438
Ashish Jain5106d362016-05-11 19:23:33 +05304439 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4440 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4441 * hence only estimate.
4442 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004443 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4444 kernel_frames = kernel_buffer_size /
4445 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304446
Weiyin Jiang4813da12020-05-28 00:37:28 +08004447 if (written_frames >= (kernel_frames + dsp_frames))
4448 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304449
Zhou Song48453a02018-01-10 17:50:59 +08004450 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304451 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004452 if (timestamp != NULL )
4453 *timestamp = out->writeAt;
4454 } else if (timestamp != NULL) {
4455 clock_gettime(CLOCK_MONOTONIC, timestamp);
4456 }
4457 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304458
Weiyin Jiang4813da12020-05-28 00:37:28 +08004459 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4460 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304461
4462 return actual_frames_rendered;
4463}
4464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4466{
4467 struct stream_out *out = (struct stream_out *)stream;
4468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004469 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470}
4471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004472static int out_set_sample_rate(struct audio_stream *stream __unused,
4473 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474{
4475 return -ENOSYS;
4476}
4477
4478static size_t out_get_buffer_size(const struct audio_stream *stream)
4479{
4480 struct stream_out *out = (struct stream_out *)stream;
4481
Varun Balaraje49253e2017-07-06 19:48:56 +05304482 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304483 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304484 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304485 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4486 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4487 else
4488 return out->compr_config.fragment_size;
4489 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004490 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304491 else if (is_offload_usecase(out->usecase) &&
4492 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304493 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004494
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004495 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004496 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497}
4498
4499static uint32_t out_get_channels(const struct audio_stream *stream)
4500{
4501 struct stream_out *out = (struct stream_out *)stream;
4502
4503 return out->channel_mask;
4504}
4505
4506static audio_format_t out_get_format(const struct audio_stream *stream)
4507{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004508 struct stream_out *out = (struct stream_out *)stream;
4509
4510 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511}
4512
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004513static int out_set_format(struct audio_stream *stream __unused,
4514 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515{
4516 return -ENOSYS;
4517}
4518
4519static int out_standby(struct audio_stream *stream)
4520{
4521 struct stream_out *out = (struct stream_out *)stream;
4522 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004523 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304525 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4526 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004528 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004530 if (adev->adm_deregister_stream)
4531 adev->adm_deregister_stream(adev->adm_data, out->handle);
4532
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004533 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004534 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004535 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004536
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004537 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004539 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4540 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304541 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004542 pthread_mutex_unlock(&adev->lock);
4543 pthread_mutex_unlock(&out->lock);
4544 ALOGD("VOIP output entered standby");
4545 return 0;
4546 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004547 if (out->pcm) {
4548 pcm_close(out->pcm);
4549 out->pcm = NULL;
4550 }
Meng Wanga09da002020-04-20 12:56:04 +08004551 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4552 if (adev->haptic_pcm) {
4553 pcm_close(adev->haptic_pcm);
4554 adev->haptic_pcm = NULL;
4555 }
4556
4557 if (adev->haptic_buffer != NULL) {
4558 free(adev->haptic_buffer);
4559 adev->haptic_buffer = NULL;
4560 adev->haptic_buffer_size = 0;
4561 }
4562 adev->haptic_pcm_device_id = 0;
4563 }
4564
Haynes Mathew George16081042017-05-31 17:16:49 -07004565 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4566 do_stop = out->playback_started;
4567 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004568
4569 if (out->mmap_shared_memory_fd >= 0) {
4570 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4571 __func__, out->mmap_shared_memory_fd);
4572 close(out->mmap_shared_memory_fd);
4573 out->mmap_shared_memory_fd = -1;
4574 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004575 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004576 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004577 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304578 out->send_next_track_params = false;
4579 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004580 out->gapless_mdata.encoder_delay = 0;
4581 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004582 if (out->compr != NULL) {
4583 compress_close(out->compr);
4584 out->compr = NULL;
4585 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004586 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004587 if (do_stop) {
4588 stop_output_stream(out);
4589 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304590 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004591 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004592 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 }
4594 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304595 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 return 0;
4597}
4598
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304599static int out_on_error(struct audio_stream *stream)
4600{
4601 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004602 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304603
4604 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004605 // always send CMD_ERROR for offload streams, this
4606 // is needed e.g. when SSR happens within compress_open
4607 // since the stream is active, offload_callback_thread is also active.
4608 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4609 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004610 }
4611 pthread_mutex_unlock(&out->lock);
4612
4613 status = out_standby(&out->stream.common);
4614
4615 lock_output_stream(out);
4616 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004617 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304618 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304619
4620 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4621 ALOGD("Setting previous card status if offline");
4622 out->prev_card_status_offline = true;
4623 }
4624
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304625 pthread_mutex_unlock(&out->lock);
4626
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004627 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304628}
4629
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304630/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004631 * standby implementation without locks, assumes that the callee already
4632 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304633 */
4634int out_standby_l(struct audio_stream *stream)
4635{
4636 struct stream_out *out = (struct stream_out *)stream;
4637 struct audio_device *adev = out->dev;
4638
4639 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4640 stream, out->usecase, use_case_table[out->usecase]);
4641
4642 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004643 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304644 if (adev->adm_deregister_stream)
4645 adev->adm_deregister_stream(adev->adm_data, out->handle);
4646
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004647 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304648 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004649 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304650
4651 out->standby = true;
4652 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4653 voice_extn_compress_voip_close_output_stream(stream);
4654 out->started = 0;
4655 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004656 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304657 return 0;
4658 } else if (!is_offload_usecase(out->usecase)) {
4659 if (out->pcm) {
4660 pcm_close(out->pcm);
4661 out->pcm = NULL;
4662 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004663 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4664 if (adev->haptic_pcm) {
4665 pcm_close(adev->haptic_pcm);
4666 adev->haptic_pcm = NULL;
4667 }
4668
4669 if (adev->haptic_buffer != NULL) {
4670 free(adev->haptic_buffer);
4671 adev->haptic_buffer = NULL;
4672 adev->haptic_buffer_size = 0;
4673 }
4674 adev->haptic_pcm_device_id = 0;
4675 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304676 } else {
4677 ALOGD("copl(%p):standby", out);
4678 out->send_next_track_params = false;
4679 out->is_compr_metadata_avail = false;
4680 out->gapless_mdata.encoder_delay = 0;
4681 out->gapless_mdata.encoder_padding = 0;
4682 if (out->compr != NULL) {
4683 compress_close(out->compr);
4684 out->compr = NULL;
4685 }
4686 }
4687 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004688 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304689 }
4690 ALOGD("%s: exit", __func__);
4691 return 0;
4692}
4693
Aalique Grahame22e49102018-12-18 14:23:57 -08004694static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695{
Aalique Grahame22e49102018-12-18 14:23:57 -08004696 struct stream_out *out = (struct stream_out *)stream;
4697
4698 // We try to get the lock for consistency,
4699 // but it isn't necessary for these variables.
4700 // If we're not in standby, we may be blocked on a write.
4701 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4702 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4703 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4704
Andy Hunga1f48fa2019-07-01 18:14:53 -07004705 char buffer[256]; // for statistics formatting
4706 if (!is_offload_usecase(out->usecase)) {
4707 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4708 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4709 }
4710
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004711 if (out->start_latency_ms.n > 0) {
4712 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4713 dprintf(fd, " Start latency ms: %s\n", buffer);
4714 }
4715
Aalique Grahame22e49102018-12-18 14:23:57 -08004716 if (locked) {
4717 pthread_mutex_unlock(&out->lock);
4718 }
4719
4720 // dump error info
4721 (void)error_log_dump(
4722 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724 return 0;
4725}
4726
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004727static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4728{
4729 int ret = 0;
4730 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004731
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004732 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004733 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004734 return -EINVAL;
4735 }
4736
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304737 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004738
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004739 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4740 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304741 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004742 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004743 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4744 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304745 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004746 }
4747
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004748 ALOGV("%s new encoder delay %u and padding %u", __func__,
4749 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4750
4751 return 0;
4752}
4753
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004754static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4755{
4756 return out == adev->primary_output || out == adev->voice_tx_output;
4757}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004758
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304759// note: this call is safe only if the stream_cb is
4760// removed first in close_output_stream (as is done now).
4761static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4762{
4763 if (!stream || !parms)
4764 return;
4765
4766 struct stream_out *out = (struct stream_out *)stream;
4767 struct audio_device *adev = out->dev;
4768
4769 card_status_t status;
4770 int card;
4771 if (parse_snd_card_status(parms, &card, &status) < 0)
4772 return;
4773
4774 pthread_mutex_lock(&adev->lock);
4775 bool valid_cb = (card == adev->snd_card);
4776 pthread_mutex_unlock(&adev->lock);
4777
4778 if (!valid_cb)
4779 return;
4780
4781 lock_output_stream(out);
4782 if (out->card_status != status)
4783 out->card_status = status;
4784 pthread_mutex_unlock(&out->lock);
4785
4786 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4787 use_case_table[out->usecase],
4788 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4789
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304790 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304791 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304792 if (voice_is_call_state_active(adev) &&
4793 out == adev->primary_output) {
4794 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4795 pthread_mutex_lock(&adev->lock);
4796 voice_stop_call(adev);
4797 adev->mode = AUDIO_MODE_NORMAL;
4798 pthread_mutex_unlock(&adev->lock);
4799 }
4800 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304801 return;
4802}
4803
Kevin Rocardfce19002017-08-07 19:21:36 -07004804static int get_alive_usb_card(struct str_parms* parms) {
4805 int card;
4806 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4807 !audio_extn_usb_alive(card)) {
4808 return card;
4809 }
4810 return -ENODEV;
4811}
4812
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004813int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004814 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004815{
4816 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004817 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004818 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 bool bypass_a2dp = false;
4820 bool reconfig = false;
4821 unsigned long service_interval = 0;
4822
4823 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004824 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4825
4826 list_init(&new_devices);
4827 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004828
4829 lock_output_stream(out);
4830 pthread_mutex_lock(&adev->lock);
4831
4832 /*
4833 * When HDMI cable is unplugged the music playback is paused and
4834 * the policy manager sends routing=0. But the audioflinger continues
4835 * to write data until standby time (3sec). As the HDMI core is
4836 * turned off, the write gets blocked.
4837 * Avoid this by routing audio to speaker until standby.
4838 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004839 if (is_single_device_type_equal(&out->device_list,
4840 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004841 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004842 !audio_extn_passthru_is_passthrough_stream(out) &&
4843 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004844 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004845 }
4846 /*
4847 * When A2DP is disconnected the
4848 * music playback is paused and the policy manager sends routing=0
4849 * But the audioflinger continues to write data until standby time
4850 * (3sec). As BT is turned off, the write gets blocked.
4851 * Avoid this by routing audio to speaker until standby.
4852 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004853 if (is_a2dp_out_device_type(&out->device_list) &&
4854 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004855 !audio_extn_a2dp_source_is_ready() &&
4856 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004857 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004858 }
4859 /*
4860 * When USB headset is disconnected the music platback paused
4861 * and the policy manager send routing=0. But if the USB is connected
4862 * back before the standby time, AFE is not closed and opened
4863 * when USB is connected back. So routing to speker will guarantee
4864 * AFE reconfiguration and AFE will be opend once USB is connected again
4865 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 if (is_usb_out_device_type(&out->device_list) &&
4867 list_empty(&new_devices) &&
4868 !audio_extn_usb_connected(NULL)) {
4869 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4870 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004871 /* To avoid a2dp to sco overlapping / BT device improper state
4872 * check with BT lib about a2dp streaming support before routing
4873 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004874 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004875 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004876 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4877 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878 //combo usecase just by pass a2dp
4879 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4880 bypass_a2dp = true;
4881 } else {
4882 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4883 /* update device to a2dp and don't route as BT returned error
4884 * However it is still possible a2dp routing called because
4885 * of current active device disconnection (like wired headset)
4886 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004887 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004888 pthread_mutex_unlock(&adev->lock);
4889 pthread_mutex_unlock(&out->lock);
4890 goto error;
4891 }
4892 }
4893 }
4894
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004895 // Workaround: If routing to an non existing usb device, fail gracefully
4896 // The routing request will otherwise block during 10 second
4897 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004898 if (is_usb_out_device_type(&new_devices)) {
4899 struct str_parms *parms =
4900 str_parms_create_str(get_usb_device_address(&new_devices));
4901 if (!parms)
4902 goto error;
4903 if ((card = get_alive_usb_card(parms)) >= 0) {
4904 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4905 pthread_mutex_unlock(&adev->lock);
4906 pthread_mutex_unlock(&out->lock);
4907 str_parms_destroy(parms);
4908 ret = -ENOSYS;
4909 goto error;
4910 }
4911 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004912 }
4913
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004914 // Workaround: If routing to an non existing hdmi device, fail gracefully
4915 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4916 (platform_get_edid_info_v2(adev->platform,
4917 out->extconn.cs.controller,
4918 out->extconn.cs.stream) != 0)) {
4919 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4920 pthread_mutex_unlock(&adev->lock);
4921 pthread_mutex_unlock(&out->lock);
4922 ret = -ENOSYS;
4923 goto error;
4924 }
4925
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004926 /*
4927 * select_devices() call below switches all the usecases on the same
4928 * backend to the new device. Refer to check_usecases_codec_backend() in
4929 * the select_devices(). But how do we undo this?
4930 *
4931 * For example, music playback is active on headset (deep-buffer usecase)
4932 * and if we go to ringtones and select a ringtone, low-latency usecase
4933 * will be started on headset+speaker. As we can't enable headset+speaker
4934 * and headset devices at the same time, select_devices() switches the music
4935 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4936 * So when the ringtone playback is completed, how do we undo the same?
4937 *
4938 * We are relying on the out_set_parameters() call on deep-buffer output,
4939 * once the ringtone playback is ended.
4940 * NOTE: We should not check if the current devices are same as new devices.
4941 * Because select_devices() must be called to switch back the music
4942 * playback to headset.
4943 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004944 if (!list_empty(&new_devices)) {
4945 bool same_dev = compare_devices(&out->device_list, &new_devices);
4946 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004947
4948 if (output_drives_call(adev, out)) {
4949 if (!voice_is_call_state_active(adev)) {
4950 if (adev->mode == AUDIO_MODE_IN_CALL) {
4951 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004952 ret = voice_start_call(adev);
4953 }
4954 } else {
4955 adev->current_call_output = out;
4956 voice_update_devices_for_all_voice_usecases(adev);
4957 }
4958 }
4959
Mingshu Pang60536d72020-09-09 15:28:22 +08004960 if (is_usb_out_device_type(&out->device_list)) {
4961 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4962 audio_extn_usb_set_service_interval(true /*playback*/,
4963 service_interval,
4964 &reconfig);
4965 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4966 }
4967
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004968 if (!out->standby) {
4969 if (!same_dev) {
4970 ALOGV("update routing change");
4971 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4972 adev->perf_lock_opts,
4973 adev->perf_lock_opts_size);
4974 if (adev->adm_on_routing_change)
4975 adev->adm_on_routing_change(adev->adm_data,
4976 out->handle);
4977 }
4978 if (!bypass_a2dp) {
4979 select_devices(adev, out->usecase);
4980 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004981 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4982 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004983 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004984 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004985 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004986 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004987 }
4988
4989 if (!same_dev) {
4990 // on device switch force swap, lower functions will make sure
4991 // to check if swap is allowed or not.
4992 platform_set_swap_channels(adev, true);
4993 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4994 }
Zhou Song1f93fa52020-11-20 13:57:39 +08004995 pthread_mutex_lock(&out->latch_lock);
4996 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
4997 if (out->a2dp_muted) {
4998 out->a2dp_muted = false;
4999 if (is_offload_usecase(out->usecase))
5000 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5001 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5002 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005003 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005004 }
Zhou Song1f93fa52020-11-20 13:57:39 +08005005 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5006 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5007 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005008 }
5009 }
5010
5011 pthread_mutex_unlock(&adev->lock);
5012 pthread_mutex_unlock(&out->lock);
5013
5014 /*handles device and call state changes*/
5015 audio_extn_extspk_update(adev->extspk);
5016
5017error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005018 ALOGV("%s: exit: code(%d)", __func__, ret);
5019 return ret;
5020}
5021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5023{
5024 struct stream_out *out = (struct stream_out *)stream;
5025 struct audio_device *adev = out->dev;
5026 struct str_parms *parms;
5027 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005028 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005029 int ext_controller = -1;
5030 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031
sangwoobc677242013-08-08 16:53:43 +09005032 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005033 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305035 if (!parms)
5036 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005037
5038 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5039 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005040 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005041 out->extconn.cs.controller = ext_controller;
5042 out->extconn.cs.stream = ext_stream;
5043 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5044 use_case_table[out->usecase], out->extconn.cs.controller,
5045 out->extconn.cs.stream);
5046 }
5047
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005048 if (out == adev->primary_output) {
5049 pthread_mutex_lock(&adev->lock);
5050 audio_extn_set_parameters(adev, parms);
5051 pthread_mutex_unlock(&adev->lock);
5052 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005053 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005054 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005055 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005056
5057 audio_extn_dts_create_state_notifier_node(out->usecase);
5058 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5059 popcount(out->channel_mask),
5060 out->playback_started);
5061
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005062 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005063 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005064
Surendar Karkaf51b5842018-04-26 11:28:38 +05305065 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5066 sizeof(value));
5067 if (err >= 0) {
5068 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5069 audio_extn_send_dual_mono_mixing_coefficients(out);
5070 }
5071
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305072 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5073 if (err >= 0) {
5074 strlcpy(out->profile, value, sizeof(out->profile));
5075 ALOGV("updating stream profile with value '%s'", out->profile);
5076 lock_output_stream(out);
5077 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5078 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005079 &out->device_list, out->flags,
5080 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305081 out->sample_rate, out->bit_width,
5082 out->channel_mask, out->profile,
5083 &out->app_type_cfg);
5084 pthread_mutex_unlock(&out->lock);
5085 }
5086
Alexy Joseph98988832017-01-13 14:56:59 -08005087 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005088 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5089 // and vendor.audio.hal.output.suspend.supported is set to true
5090 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005091 //check suspend parameter only for low latency and if the property
5092 //is enabled
5093 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5094 ALOGI("%s: got suspend_playback %s", __func__, value);
5095 lock_output_stream(out);
5096 if (!strncmp(value, "false", 5)) {
5097 //suspend_playback=false is supposed to set QOS value back to 75%
5098 //the mixer control sent with value Enable will achieve that
5099 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5100 } else if (!strncmp (value, "true", 4)) {
5101 //suspend_playback=true is supposed to remove QOS value
5102 //resetting the mixer control will set the default value
5103 //for the mixer control which is Disable and this removes the QOS vote
5104 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5105 } else {
5106 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5107 " got %s", __func__, value);
5108 ret = -1;
5109 }
5110
5111 if (ret != 0) {
5112 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5113 __func__, out->pm_qos_mixer_path, ret);
5114 }
5115
5116 pthread_mutex_unlock(&out->lock);
5117 }
5118 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005119
Alexy Joseph98988832017-01-13 14:56:59 -08005120 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305122error:
Eric Laurent994a6932013-07-17 11:51:42 -07005123 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005124 return ret;
5125}
5126
Paul McLeana50b7332018-12-17 08:24:21 -07005127static int in_set_microphone_direction(const struct audio_stream_in *stream,
5128 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005129 struct stream_in *in = (struct stream_in *)stream;
5130
5131 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5132
5133 in->direction = dir;
5134
5135 if (in->standby)
5136 return 0;
5137
5138 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005139}
5140
5141static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005142 struct stream_in *in = (struct stream_in *)stream;
5143
5144 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5145
5146 if (zoom > 1.0 || zoom < -1.0)
5147 return -EINVAL;
5148
5149 in->zoom = zoom;
5150
5151 if (in->standby)
5152 return 0;
5153
5154 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005155}
5156
5157
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005158static bool stream_get_parameter_channels(struct str_parms *query,
5159 struct str_parms *reply,
5160 audio_channel_mask_t *supported_channel_masks) {
5161 int ret = -1;
5162 char value[512];
5163 bool first = true;
5164 size_t i, j;
5165
5166 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5167 ret = 0;
5168 value[0] = '\0';
5169 i = 0;
5170 while (supported_channel_masks[i] != 0) {
5171 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5172 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5173 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305174 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005175
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305176 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005177 first = false;
5178 break;
5179 }
5180 }
5181 i++;
5182 }
5183 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5184 }
5185 return ret == 0;
5186}
5187
5188static bool stream_get_parameter_formats(struct str_parms *query,
5189 struct str_parms *reply,
5190 audio_format_t *supported_formats) {
5191 int ret = -1;
5192 char value[256];
5193 size_t i, j;
5194 bool first = true;
5195
5196 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5197 ret = 0;
5198 value[0] = '\0';
5199 i = 0;
5200 while (supported_formats[i] != 0) {
5201 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5202 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5203 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305204 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005205 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305206 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005207 first = false;
5208 break;
5209 }
5210 }
5211 i++;
5212 }
5213 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5214 }
5215 return ret == 0;
5216}
5217
5218static bool stream_get_parameter_rates(struct str_parms *query,
5219 struct str_parms *reply,
5220 uint32_t *supported_sample_rates) {
5221
5222 int i;
5223 char value[256];
5224 int ret = -1;
5225 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5226 ret = 0;
5227 value[0] = '\0';
5228 i=0;
5229 int cursor = 0;
5230 while (supported_sample_rates[i]) {
5231 int avail = sizeof(value) - cursor;
5232 ret = snprintf(value + cursor, avail, "%s%d",
5233 cursor > 0 ? "|" : "",
5234 supported_sample_rates[i]);
5235 if (ret < 0 || ret >= avail) {
5236 // if cursor is at the last element of the array
5237 // overwrite with \0 is duplicate work as
5238 // snprintf already put a \0 in place.
5239 // else
5240 // we had space to write the '|' at value[cursor]
5241 // (which will be overwritten) or no space to fill
5242 // the first element (=> cursor == 0)
5243 value[cursor] = '\0';
5244 break;
5245 }
5246 cursor += ret;
5247 ++i;
5248 }
5249 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5250 value);
5251 }
5252 return ret >= 0;
5253}
5254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5256{
5257 struct stream_out *out = (struct stream_out *)stream;
5258 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005259 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260 char value[256];
5261 struct str_parms *reply = str_parms_create();
5262 size_t i, j;
5263 int ret;
5264 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005265
5266 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005267 if (reply) {
5268 str_parms_destroy(reply);
5269 }
5270 if (query) {
5271 str_parms_destroy(query);
5272 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005273 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5274 return NULL;
5275 }
5276
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005277 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5279 if (ret >= 0) {
5280 value[0] = '\0';
5281 i = 0;
5282 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005283 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5284 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005285 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005286 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005287 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005288 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005289 first = false;
5290 break;
5291 }
5292 }
5293 i++;
5294 }
5295 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5296 str = str_parms_to_str(reply);
5297 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005298 voice_extn_out_get_parameters(out, query, reply);
5299 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005301
Alexy Joseph62142aa2015-11-16 15:10:34 -08005302
5303 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5304 if (ret >= 0) {
5305 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305306 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5307 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005308 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305309 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005310 } else {
5311 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305312 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005313 }
5314 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005315 if (str)
5316 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005317 str = str_parms_to_str(reply);
5318 }
5319
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005320 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5321 if (ret >= 0) {
5322 value[0] = '\0';
5323 i = 0;
5324 first = true;
5325 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005326 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5327 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005328 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005329 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005330 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005331 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005332 first = false;
5333 break;
5334 }
5335 }
5336 i++;
5337 }
5338 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005339 if (str)
5340 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005341 str = str_parms_to_str(reply);
5342 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005343
5344 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5345 if (ret >= 0) {
5346 value[0] = '\0';
5347 i = 0;
5348 first = true;
5349 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005350 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5351 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005352 if (!first) {
5353 strlcat(value, "|", sizeof(value));
5354 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005355 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005356 first = false;
5357 break;
5358 }
5359 }
5360 i++;
5361 }
5362 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5363 if (str)
5364 free(str);
5365 str = str_parms_to_str(reply);
5366 }
5367
Alexy Joseph98988832017-01-13 14:56:59 -08005368 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5369 //only low latency track supports suspend_resume
5370 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005371 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005372 if (str)
5373 free(str);
5374 str = str_parms_to_str(reply);
5375 }
5376
5377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378 str_parms_destroy(query);
5379 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005380 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005381 return str;
5382}
5383
5384static uint32_t out_get_latency(const struct audio_stream_out *stream)
5385{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005386 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005388 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005389
Alexy Josephaa54c872014-12-03 02:46:47 -08005390 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305391 lock_output_stream(out);
5392 latency = audio_extn_utils_compress_get_dsp_latency(out);
5393 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005394 } else if ((out->realtime) ||
5395 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005396 // since the buffer won't be filled up faster than realtime,
5397 // return a smaller number
5398 if (out->config.rate)
5399 period_ms = (out->af_period_multiplier * out->config.period_size *
5400 1000) / (out->config.rate);
5401 else
5402 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005403 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005404 } else {
5405 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005406 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005407 }
5408
Zhou Songd2537a02020-06-11 22:04:46 +08005409 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005410 latency += audio_extn_a2dp_get_encoder_latency();
5411
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305412 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005413 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005414}
5415
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305416static float AmpToDb(float amplification)
5417{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305418 float db = DSD_VOLUME_MIN_DB;
5419 if (amplification > 0) {
5420 db = 20 * log10(amplification);
5421 if(db < DSD_VOLUME_MIN_DB)
5422 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305423 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305424 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305425}
5426
Arun Mirpuri5d170872019-03-26 13:21:31 -07005427static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5428 float right)
5429{
5430 struct stream_out *out = (struct stream_out *)stream;
5431 long volume = 0;
5432 char mixer_ctl_name[128] = "";
5433 struct audio_device *adev = out->dev;
5434 struct mixer_ctl *ctl = NULL;
5435 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5436 PCM_PLAYBACK);
5437
5438 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5439 "Playback %d Volume", pcm_device_id);
5440 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5441 if (!ctl) {
5442 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5443 __func__, mixer_ctl_name);
5444 return -EINVAL;
5445 }
5446 if (left != right)
5447 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5448 __func__, left, right);
5449 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5450 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5451 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5452 __func__, mixer_ctl_name, volume);
5453 return -EINVAL;
5454 }
5455 return 0;
5456}
5457
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305458static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5459 float right)
5460{
5461 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305462 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305463 char mixer_ctl_name[128];
5464 struct audio_device *adev = out->dev;
5465 struct mixer_ctl *ctl;
5466 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5467 PCM_PLAYBACK);
5468
5469 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5470 "Compress Playback %d Volume", pcm_device_id);
5471 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5472 if (!ctl) {
5473 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5474 __func__, mixer_ctl_name);
5475 return -EINVAL;
5476 }
5477 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5478 __func__, mixer_ctl_name, left, right);
5479 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5480 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5481 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5482
5483 return 0;
5484}
5485
Zhou Song2b8f28f2017-09-11 10:51:38 +08005486static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5487 float right)
5488{
5489 struct stream_out *out = (struct stream_out *)stream;
5490 char mixer_ctl_name[] = "App Type Gain";
5491 struct audio_device *adev = out->dev;
5492 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305493 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005494
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005495 if (!is_valid_volume(left, right)) {
5496 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5497 __func__, left, right);
5498 return -EINVAL;
5499 }
5500
Zhou Song2b8f28f2017-09-11 10:51:38 +08005501 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5502 if (!ctl) {
5503 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5504 __func__, mixer_ctl_name);
5505 return -EINVAL;
5506 }
5507
5508 set_values[0] = 0; //0: Rx Session 1:Tx Session
5509 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305510 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5511 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005512
5513 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5514 return 0;
5515}
5516
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305517static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5518 float right)
5519{
5520 struct stream_out *out = (struct stream_out *)stream;
5521 /* Volume control for pcm playback */
5522 if (left != right) {
5523 return -EINVAL;
5524 } else {
5525 char mixer_ctl_name[128];
5526 struct audio_device *adev = out->dev;
5527 struct mixer_ctl *ctl;
5528 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5529 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5530 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5531 if (!ctl) {
5532 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5533 return -EINVAL;
5534 }
5535
5536 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5537 int ret = mixer_ctl_set_value(ctl, 0, volume);
5538 if (ret < 0) {
5539 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5540 return -EINVAL;
5541 }
5542
5543 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5544
5545 return 0;
5546 }
5547}
5548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549static int out_set_volume(struct audio_stream_out *stream, float left,
5550 float right)
5551{
Eric Laurenta9024de2013-04-04 09:19:12 -07005552 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005553 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305554 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005555
Arun Mirpuri5d170872019-03-26 13:21:31 -07005556 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005557 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5558 /* only take left channel into account: the API is for stereo anyway */
5559 out->muted = (left == 0.0f);
5560 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005561 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305562 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005563 /*
5564 * Set mute or umute on HDMI passthrough stream.
5565 * Only take left channel into account.
5566 * Mute is 0 and unmute 1
5567 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305568 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305569 } else if (out->format == AUDIO_FORMAT_DSD){
5570 char mixer_ctl_name[128] = "DSD Volume";
5571 struct audio_device *adev = out->dev;
5572 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5573
5574 if (!ctl) {
5575 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5576 __func__, mixer_ctl_name);
5577 return -EINVAL;
5578 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305579 volume[0] = (long)(AmpToDb(left));
5580 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305581 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5582 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005583 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005584 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005585 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5586 struct listnode *node = NULL;
5587 list_for_each(node, &adev->active_outputs_list) {
5588 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5589 streams_output_ctxt_t,
5590 list);
5591 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5592 out->volume_l = out_ctxt->output->volume_l;
5593 out->volume_r = out_ctxt->output->volume_r;
5594 }
5595 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005596 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005597 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005598 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5599 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005600 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005601 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005602 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005603 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005604 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5605 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305606 ret = out_set_compr_volume(stream, left, right);
5607 out->volume_l = left;
5608 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005609 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305610 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005611 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005612 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005613 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5614 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song1f93fa52020-11-20 13:57:39 +08005615 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005616 if (!out->standby) {
5617 audio_extn_utils_send_app_type_gain(out->dev,
5618 out->app_type_cfg.app_type,
5619 &out->app_type_cfg.gain[0]);
Zhou Song1f93fa52020-11-20 13:57:39 +08005620 if (!out->a2dp_muted)
5621 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005622 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005623 out->volume_l = left;
5624 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005625 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005626 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005627 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5628 ALOGV("%s: MMAP set volume called", __func__);
5629 if (!out->standby)
5630 ret = out_set_mmap_volume(stream, left, right);
5631 out->volume_l = left;
5632 out->volume_r = right;
5633 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305634 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305635 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5636 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Song1f93fa52020-11-20 13:57:39 +08005637 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305638 /* Volume control for pcm playback */
Zhou Song1f93fa52020-11-20 13:57:39 +08005639 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305640 ret = out_set_pcm_volume(stream, left, right);
5641 else
5642 out->apply_volume = true;
5643
5644 out->volume_l = left;
5645 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005646 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305647 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005648 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5649 ALOGV("%s: bus device set volume called", __func__);
Zhou Song1f93fa52020-11-20 13:57:39 +08005650 pthread_mutex_lock(&out->latch_lock);
5651 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005652 ret = out_set_pcm_volume(stream, left, right);
5653 out->volume_l = left;
5654 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005655 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005656 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005657 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005659 return -ENOSYS;
5660}
5661
Zhou Songc9672822017-08-16 16:01:39 +08005662static void update_frames_written(struct stream_out *out, size_t bytes)
5663{
5664 size_t bpf = 0;
5665
5666 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5667 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5668 bpf = 1;
5669 else if (!is_offload_usecase(out->usecase))
5670 bpf = audio_bytes_per_sample(out->format) *
5671 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005672
5673 pthread_mutex_lock(&out->position_query_lock);
5674 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005675 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005676 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5677 }
5678 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005679}
5680
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005681int split_and_write_audio_haptic_data(struct stream_out *out,
5682 const void *buffer, size_t bytes_to_write)
5683{
5684 struct audio_device *adev = out->dev;
5685
5686 int ret = 0;
5687 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5688 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5689 size_t frame_size = channel_count * bytes_per_sample;
5690 size_t frame_count = bytes_to_write / frame_size;
5691
5692 bool force_haptic_path =
5693 property_get_bool("vendor.audio.test_haptic", false);
5694
5695 // extract Haptics data from Audio buffer
5696 bool alloc_haptic_buffer = false;
5697 int haptic_channel_count = adev->haptics_config.channels;
5698 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5699 size_t audio_frame_size = frame_size - haptic_frame_size;
5700 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5701
5702 if (adev->haptic_buffer == NULL) {
5703 alloc_haptic_buffer = true;
5704 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5705 free(adev->haptic_buffer);
5706 adev->haptic_buffer_size = 0;
5707 alloc_haptic_buffer = true;
5708 }
5709
5710 if (alloc_haptic_buffer) {
5711 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005712 if(adev->haptic_buffer == NULL) {
5713 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5714 return -ENOMEM;
5715 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005716 adev->haptic_buffer_size = total_haptic_buffer_size;
5717 }
5718
5719 size_t src_index = 0, aud_index = 0, hap_index = 0;
5720 uint8_t *audio_buffer = (uint8_t *)buffer;
5721 uint8_t *haptic_buffer = adev->haptic_buffer;
5722
5723 // This is required for testing only. This works for stereo data only.
5724 // One channel is fed to audio stream and other to haptic stream for testing.
5725 if (force_haptic_path)
5726 audio_frame_size = haptic_frame_size = bytes_per_sample;
5727
5728 for (size_t i = 0; i < frame_count; i++) {
5729 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5730 audio_frame_size);
5731 aud_index += audio_frame_size;
5732 src_index += audio_frame_size;
5733
5734 if (adev->haptic_pcm)
5735 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5736 haptic_frame_size);
5737 hap_index += haptic_frame_size;
5738 src_index += haptic_frame_size;
5739
5740 // This is required for testing only.
5741 // Discard haptic channel data.
5742 if (force_haptic_path)
5743 src_index += haptic_frame_size;
5744 }
5745
5746 // write to audio pipeline
5747 ret = pcm_write(out->pcm, (void *)audio_buffer,
5748 frame_count * audio_frame_size);
5749
5750 // write to haptics pipeline
5751 if (adev->haptic_pcm)
5752 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5753 frame_count * haptic_frame_size);
5754
5755 return ret;
5756}
5757
Aalique Grahame22e49102018-12-18 14:23:57 -08005758#ifdef NO_AUDIO_OUT
5759static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5760 const void *buffer __unused, size_t bytes)
5761{
5762 struct stream_out *out = (struct stream_out *)stream;
5763
5764 /* No Output device supported other than BT for playback.
5765 * Sleep for the amount of buffer duration
5766 */
5767 lock_output_stream(out);
5768 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5769 (const struct audio_stream_out *)&out->stream) /
5770 out_get_sample_rate(&out->stream.common));
5771 pthread_mutex_unlock(&out->lock);
5772 return bytes;
5773}
5774#endif
5775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5777 size_t bytes)
5778{
5779 struct stream_out *out = (struct stream_out *)stream;
5780 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005781 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305782 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005783 const size_t frame_size = audio_stream_out_frame_size(stream);
5784 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305785 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005786 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005787
Haynes Mathew George380745d2017-10-04 15:27:45 -07005788 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005789 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305790
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305791 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005792
Dhananjay Kumarac341582017-02-23 23:42:25 +05305793 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305794 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305795 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5796 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005797 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305798 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305799 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305800 ALOGD(" %s: sound card is not active/SSR state", __func__);
5801 ret= -EIO;
5802 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305803 }
5804 }
5805
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305806 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305807 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305808 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305809 goto exit;
5810 }
5811
Haynes Mathew George16081042017-05-31 17:16:49 -07005812 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5813 ret = -EINVAL;
5814 goto exit;
5815 }
5816
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005817 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305818 !out->is_iec61937_info_available) {
5819
5820 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5821 out->is_iec61937_info_available = true;
5822 } else if (audio_extn_passthru_is_enabled()) {
5823 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305824 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305825
5826 if((out->format == AUDIO_FORMAT_DTS) ||
5827 (out->format == AUDIO_FORMAT_DTS_HD)) {
5828 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5829 buffer, bytes);
5830 if (ret) {
5831 if (ret != -ENOSYS) {
5832 out->is_iec61937_info_available = false;
5833 ALOGD("iec61937 transmission info not yet updated retry");
5834 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305835 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305836 /* if stream has started and after that there is
5837 * stream config change (iec transmission config)
5838 * then trigger select_device to update backend configuration.
5839 */
5840 out->stream_config_changed = true;
5841 pthread_mutex_lock(&adev->lock);
5842 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305843 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005844 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305845 ret = -EINVAL;
5846 goto exit;
5847 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305848 pthread_mutex_unlock(&adev->lock);
5849 out->stream_config_changed = false;
5850 out->is_iec61937_info_available = true;
5851 }
5852 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305853
Meng Wang4c32fb42020-01-16 17:57:11 +08005854#ifdef AUDIO_GKI_ENABLED
5855 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5856 compr_passthr = out->compr_config.codec->reserved[0];
5857#else
5858 compr_passthr = out->compr_config.codec->compr_passthr;
5859#endif
5860
Garmond Leung317cbf12017-09-13 16:20:50 -07005861 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005862 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305863 (out->is_iec61937_info_available == true)) {
5864 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5865 ret = -EINVAL;
5866 goto exit;
5867 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305868 }
5869 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305870
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005871 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005872 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005873 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5874 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Song9ebf6792020-09-23 22:49:01 +08005875 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305876 ret = -EIO;
5877 goto exit;
5878 }
5879 }
5880 }
5881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005882 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005883 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005884 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5885
Eric Laurent150dbfe2013-02-27 14:31:02 -08005886 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005887 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5888 ret = voice_extn_compress_voip_start_output_stream(out);
5889 else
5890 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005891 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005892 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005893 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005894 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005895 goto exit;
5896 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305897 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005898 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005899
5900 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005901 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005902 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305903 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005904 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005905 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305906
5907 if ((out->is_iec61937_info_available == true) &&
5908 (audio_extn_passthru_is_passthrough_stream(out))&&
5909 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5910 ret = -EINVAL;
5911 goto exit;
5912 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305913 if (out->set_dual_mono)
5914 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005915
5916 // log startup time in ms.
5917 simple_stats_log(
5918 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005919 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005920
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005921 if (adev->is_channel_status_set == false &&
5922 compare_device_type(&out->device_list,
5923 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005924 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305925 adev->is_channel_status_set = true;
5926 }
5927
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305928 if ((adev->use_old_pspd_mix_ctrl == true) &&
5929 (out->pspd_coeff_sent == false)) {
5930 /*
5931 * Need to resend pspd coefficients after stream started for
5932 * older kernel version as it does not save the coefficients
5933 * and also stream has to be started for coeff to apply.
5934 */
5935 usecase = get_usecase_from_list(adev, out->usecase);
5936 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305937 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305938 out->pspd_coeff_sent = true;
5939 }
5940 }
5941
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005942 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005943 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005944 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005945 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005946 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5947 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305948 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5949 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005950 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305951 out->send_next_track_params = false;
5952 out->is_compr_metadata_avail = false;
5953 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005954 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305955 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305956 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005957
Ashish Jain83a6cc22016-06-28 14:34:17 +05305958 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305959 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305960 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305961 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005962 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305963 return -EINVAL;
5964 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305965 audio_format_t dst_format = out->hal_op_format;
5966 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305967
Dieter Luecking5d57def2018-09-07 14:23:37 +02005968 /* prevent division-by-zero */
5969 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5970 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5971 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5972 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305973 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005974 ATRACE_END();
5975 return -EINVAL;
5976 }
5977
Ashish Jainf1eaa582016-05-23 20:54:24 +05305978 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5979 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5980
Ashish Jain83a6cc22016-06-28 14:34:17 +05305981 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305982 dst_format,
5983 buffer,
5984 src_format,
5985 frames);
5986
Ashish Jain83a6cc22016-06-28 14:34:17 +05305987 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305988 bytes_to_write);
5989
5990 /*Convert written bytes in audio flinger format*/
5991 if (ret > 0)
5992 ret = ((ret * format_to_bitwidth_table[out->format]) /
5993 format_to_bitwidth_table[dst_format]);
5994 }
5995 } else
5996 ret = compress_write(out->compr, buffer, bytes);
5997
Zhou Songc9672822017-08-16 16:01:39 +08005998 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5999 update_frames_written(out, bytes);
6000
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306001 if (ret < 0)
6002 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006003 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306004 /*msg to cb thread only if non blocking write is enabled*/
6005 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306006 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006007 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306008 } else if (-ENETRESET == ret) {
6009 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306010 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306011 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306012 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006013 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306014 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006015 }
Ashish Jain5106d362016-05-11 19:23:33 +05306016
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306017 /* Call compr start only when non-zero bytes of data is there to be rendered */
6018 if (!out->playback_started && ret > 0) {
6019 int status = compress_start(out->compr);
6020 if (status < 0) {
6021 ret = status;
6022 ALOGE("%s: compr start failed with err %d", __func__, errno);
6023 goto exit;
6024 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006025 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006026 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006027 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006028 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006029 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006030
6031 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6032 popcount(out->channel_mask),
6033 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006034 }
6035 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006036 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006037 return ret;
6038 } else {
6039 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006040 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006041 if (out->muted)
6042 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006043 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6044 __func__, frames, frame_size, bytes_to_write);
6045
Aalique Grahame22e49102018-12-18 14:23:57 -08006046 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006047 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6048 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6049 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006050 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6051 int16_t *src = (int16_t *)buffer;
6052 int16_t *dst = (int16_t *)buffer;
6053
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006054 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006055 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006056 "out_write called for %s use case with wrong properties",
6057 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006058
6059 /*
6060 * FIXME: this can be removed once audio flinger mixer supports
6061 * mono output
6062 */
6063
6064 /*
6065 * Code below goes over each frame in the buffer and adds both
6066 * L and R samples and then divides by 2 to convert to mono
6067 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006068 if (channel_count == 2) {
6069 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6070 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6071 }
6072 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006073 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006074 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006075
6076 // Note: since out_get_presentation_position() is called alternating with out_write()
6077 // by AudioFlinger, we can check underruns using the prior timestamp read.
6078 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6079 if (out->last_fifo_valid) {
6080 // compute drain to see if there is an underrun.
6081 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306082 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6083 int64_t frames_by_time =
6084 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6085 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006086 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6087
6088 if (underrun > 0) {
6089 simple_stats_log(&out->fifo_underruns, underrun);
6090
6091 ALOGW("%s: underrun(%lld) "
6092 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6093 __func__,
6094 (long long)out->fifo_underruns.n,
6095 (long long)frames_by_time,
6096 (long long)out->last_fifo_frames_remaining);
6097 }
6098 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6099 }
6100
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306101 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006102
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006103 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006104
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006105 if (out->config.rate)
6106 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6107 out->config.rate;
6108
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006109 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006110 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6111
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006112 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006113 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006114 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306115 out->convert_buffer != NULL) {
6116
6117 memcpy_by_audio_format(out->convert_buffer,
6118 out->hal_op_format,
6119 buffer,
6120 out->hal_ip_format,
6121 out->config.period_size * out->config.channels);
6122
6123 ret = pcm_write(out->pcm, out->convert_buffer,
6124 (out->config.period_size *
6125 out->config.channels *
6126 format_to_bitwidth_table[out->hal_op_format]));
6127 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306128 /*
6129 * To avoid underrun in DSP when the application is not pumping
6130 * data at required rate, check for the no. of bytes and ignore
6131 * pcm_write if it is less than actual buffer size.
6132 * It is a work around to a change in compress VOIP driver.
6133 */
6134 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6135 bytes < (out->config.period_size * out->config.channels *
6136 audio_bytes_per_sample(out->format))) {
6137 size_t voip_buf_size =
6138 out->config.period_size * out->config.channels *
6139 audio_bytes_per_sample(out->format);
6140 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6141 __func__, bytes, voip_buf_size);
6142 usleep(((uint64_t)voip_buf_size - bytes) *
6143 1000000 / audio_stream_out_frame_size(stream) /
6144 out_get_sample_rate(&out->stream.common));
6145 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006146 } else {
6147 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6148 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6149 else
6150 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6151 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306152 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006153
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006154 release_out_focus(out);
6155
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306156 if (ret < 0)
6157 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006158 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306159 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006160 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006161 }
6162
6163exit:
Zhou Songc9672822017-08-16 16:01:39 +08006164 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306165 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306166 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006168 pthread_mutex_unlock(&out->lock);
6169
6170 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006171 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006172 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306173 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306174 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306175 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306176 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306177 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306178 out->standby = true;
6179 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306180 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006181 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6182 /* prevent division-by-zero */
6183 uint32_t stream_size = audio_stream_out_frame_size(stream);
6184 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006185
Dieter Luecking5d57def2018-09-07 14:23:37 +02006186 if ((stream_size == 0) || (srate == 0)) {
6187 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6188 ATRACE_END();
6189 return -EINVAL;
6190 }
6191 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6192 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006193 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306194 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006195 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006196 return ret;
6197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006198 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006199 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 return bytes;
6201}
6202
6203static int out_get_render_position(const struct audio_stream_out *stream,
6204 uint32_t *dsp_frames)
6205{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006206 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006207
6208 if (dsp_frames == NULL)
6209 return -EINVAL;
6210
6211 *dsp_frames = 0;
6212 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006213 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306214
6215 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6216 * this operation and adev_close_output_stream(where out gets reset).
6217 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306218 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006219 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306220 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006221 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306222 return 0;
6223 }
6224
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006225 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306226 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306227 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006228 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306229 if (ret < 0)
6230 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006231 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306232 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006233 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306234 if (-ENETRESET == ret) {
6235 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306236 out->card_status = CARD_STATUS_OFFLINE;
6237 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306238 } else if(ret < 0) {
6239 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306240 ret = -EINVAL;
6241 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306242 /*
6243 * Handle corner case where compress session is closed during SSR
6244 * and timestamp is queried
6245 */
6246 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306247 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306248 } else if (out->prev_card_status_offline) {
6249 ALOGE("ERROR: previously sound card was offline,return error");
6250 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306251 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306252 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006253 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306254 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306255 pthread_mutex_unlock(&out->lock);
6256 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006257 } else if (audio_is_linear_pcm(out->format)) {
6258 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006259 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006260 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006261 } else
6262 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263}
6264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006265static int out_add_audio_effect(const struct audio_stream *stream __unused,
6266 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006267{
6268 return 0;
6269}
6270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006271static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6272 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273{
6274 return 0;
6275}
6276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006277static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6278 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006279{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306280 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006281}
6282
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006283static int out_get_presentation_position(const struct audio_stream_out *stream,
6284 uint64_t *frames, struct timespec *timestamp)
6285{
6286 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306287 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006288 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006289
Ashish Jain5106d362016-05-11 19:23:33 +05306290 /* below piece of code is not guarded against any lock because audioFliner serializes
6291 * this operation and adev_close_output_stream( where out gets reset).
6292 */
6293 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306294 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006295 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306296 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6297 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6298 return 0;
6299 }
6300
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006301 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006302
Ashish Jain5106d362016-05-11 19:23:33 +05306303 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6304 ret = compress_get_tstamp(out->compr, &dsp_frames,
6305 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006306 // Adjustment accounts for A2dp encoder latency with offload usecases
6307 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006308 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006309 unsigned long offset =
6310 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6311 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6312 }
Ashish Jain5106d362016-05-11 19:23:33 +05306313 ALOGVV("%s rendered frames %ld sample_rate %d",
6314 __func__, dsp_frames, out->sample_rate);
6315 *frames = dsp_frames;
6316 if (ret < 0)
6317 ret = -errno;
6318 if (-ENETRESET == ret) {
6319 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306320 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306321 ret = -EINVAL;
6322 } else
6323 ret = 0;
6324 /* this is the best we can do */
6325 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006326 } else {
6327 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006328 unsigned int avail;
6329 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006330 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006331 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006332
Andy Hunga1f48fa2019-07-01 18:14:53 -07006333 if (out->kernel_buffer_size > avail) {
6334 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6335 } else {
6336 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6337 __func__, avail, out->kernel_buffer_size);
6338 avail = out->kernel_buffer_size;
6339 frames_temp = out->last_fifo_frames_remaining = 0;
6340 }
6341 out->last_fifo_valid = true;
6342 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6343
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006344 if (out->written >= frames_temp)
6345 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006346
Andy Hunga1f48fa2019-07-01 18:14:53 -07006347 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6348 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6349
Weiyin Jiangd4633762018-03-16 12:05:03 +08006350 // This adjustment accounts for buffering after app processor.
6351 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006352 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006353 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006354 if (signed_frames >= frames_temp)
6355 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006356
Weiyin Jiangd4633762018-03-16 12:05:03 +08006357 // Adjustment accounts for A2dp encoder latency with non offload usecases
6358 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006359 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006360 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6361 if (signed_frames >= frames_temp)
6362 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006363 }
6364
6365 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006366 *frames = signed_frames;
6367 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006368 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006369 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6370 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006371 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306372 *frames = out->written;
6373 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306374 if (is_offload_usecase(out->usecase))
6375 ret = -EINVAL;
6376 else
6377 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006378 }
6379 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006380 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006381 return ret;
6382}
6383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006384static int out_set_callback(struct audio_stream_out *stream,
6385 stream_callback_t callback, void *cookie)
6386{
6387 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006388 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006389
6390 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006391 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006392 out->client_callback = callback;
6393 out->client_cookie = cookie;
6394 if (out->adsp_hdlr_stream_handle) {
6395 ret = audio_extn_adsp_hdlr_stream_set_callback(
6396 out->adsp_hdlr_stream_handle,
6397 callback,
6398 cookie);
6399 if (ret)
6400 ALOGW("%s:adsp hdlr callback registration failed %d",
6401 __func__, ret);
6402 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 pthread_mutex_unlock(&out->lock);
6404 return 0;
6405}
6406
6407static int out_pause(struct audio_stream_out* stream)
6408{
6409 struct stream_out *out = (struct stream_out *)stream;
6410 int status = -ENOSYS;
6411 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006412 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006413 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306414 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006415 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006416 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006417 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306418 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306419 status = compress_pause(out->compr);
6420
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006421 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006422
Mingming Yin21854652016-04-13 11:54:02 -07006423 if (audio_extn_passthru_is_active()) {
6424 ALOGV("offload use case, pause passthru");
6425 audio_extn_passthru_on_pause(out);
6426 }
6427
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306428 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006429 audio_extn_dts_notify_playback_state(out->usecase, 0,
6430 out->sample_rate, popcount(out->channel_mask),
6431 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006432 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006433 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006434 pthread_mutex_unlock(&out->lock);
6435 }
6436 return status;
6437}
6438
6439static int out_resume(struct audio_stream_out* stream)
6440{
6441 struct stream_out *out = (struct stream_out *)stream;
6442 int status = -ENOSYS;
6443 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006444 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006445 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306446 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006447 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006448 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006449 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306450 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306451 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006452 }
6453 if (!status) {
6454 out->offload_state = OFFLOAD_STATE_PLAYING;
6455 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306456 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006457 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6458 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006459 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006460 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006461 pthread_mutex_unlock(&out->lock);
6462 }
6463 return status;
6464}
6465
6466static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6467{
6468 struct stream_out *out = (struct stream_out *)stream;
6469 int status = -ENOSYS;
6470 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006471 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006472 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006473 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6474 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6475 else
6476 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6477 pthread_mutex_unlock(&out->lock);
6478 }
6479 return status;
6480}
6481
6482static int out_flush(struct audio_stream_out* stream)
6483{
6484 struct stream_out *out = (struct stream_out *)stream;
6485 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006486 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006487 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006488 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006489 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006490 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manamfeeb1162020-12-24 14:08:04 +05306491 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006492 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006493 } else {
6494 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manamfeeb1162020-12-24 14:08:04 +05306495 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006496 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006497 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006498 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006499 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006500 return 0;
6501 }
6502 return -ENOSYS;
6503}
6504
Haynes Mathew George16081042017-05-31 17:16:49 -07006505static int out_stop(const struct audio_stream_out* stream)
6506{
6507 struct stream_out *out = (struct stream_out *)stream;
6508 struct audio_device *adev = out->dev;
6509 int ret = -ENOSYS;
6510
6511 ALOGV("%s", __func__);
6512 pthread_mutex_lock(&adev->lock);
6513 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6514 out->playback_started && out->pcm != NULL) {
6515 pcm_stop(out->pcm);
6516 ret = stop_output_stream(out);
6517 out->playback_started = false;
6518 }
6519 pthread_mutex_unlock(&adev->lock);
6520 return ret;
6521}
6522
6523static int out_start(const struct audio_stream_out* stream)
6524{
6525 struct stream_out *out = (struct stream_out *)stream;
6526 struct audio_device *adev = out->dev;
6527 int ret = -ENOSYS;
6528
6529 ALOGV("%s", __func__);
6530 pthread_mutex_lock(&adev->lock);
6531 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6532 !out->playback_started && out->pcm != NULL) {
6533 ret = start_output_stream(out);
6534 if (ret == 0) {
6535 out->playback_started = true;
6536 }
6537 }
6538 pthread_mutex_unlock(&adev->lock);
6539 return ret;
6540}
6541
6542/*
6543 * Modify config->period_count based on min_size_frames
6544 */
6545static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6546{
6547 int periodCountRequested = (min_size_frames + config->period_size - 1)
6548 / config->period_size;
6549 int periodCount = MMAP_PERIOD_COUNT_MIN;
6550
6551 ALOGV("%s original config.period_size = %d config.period_count = %d",
6552 __func__, config->period_size, config->period_count);
6553
6554 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6555 periodCount *= 2;
6556 }
6557 config->period_count = periodCount;
6558
6559 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6560}
6561
Phil Burkfe17efd2019-03-25 10:23:35 -07006562// Read offset for the positional timestamp from a persistent vendor property.
6563// This is to workaround apparent inaccuracies in the timing information that
6564// is used by the AAudio timing model. The inaccuracies can cause glitches.
6565static int64_t get_mmap_out_time_offset() {
6566 const int32_t kDefaultOffsetMicros = 0;
6567 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006568 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006569 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6570 return mmap_time_offset_micros * (int64_t)1000;
6571}
6572
Haynes Mathew George16081042017-05-31 17:16:49 -07006573static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6574 int32_t min_size_frames,
6575 struct audio_mmap_buffer_info *info)
6576{
6577 struct stream_out *out = (struct stream_out *)stream;
6578 struct audio_device *adev = out->dev;
6579 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006580 unsigned int offset1 = 0;
6581 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006582 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006583 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006584 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006585
Arun Mirpuri5d170872019-03-26 13:21:31 -07006586 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306587 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006588 pthread_mutex_lock(&adev->lock);
6589
Sharad Sanglec6f32552018-05-04 16:15:38 +05306590 if (CARD_STATUS_OFFLINE == out->card_status ||
6591 CARD_STATUS_OFFLINE == adev->card_status) {
6592 ALOGW("out->card_status or adev->card_status offline, try again");
6593 ret = -EIO;
6594 goto exit;
6595 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306596 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006597 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6598 ret = -EINVAL;
6599 goto exit;
6600 }
6601 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6602 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6603 ret = -ENOSYS;
6604 goto exit;
6605 }
6606 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6607 if (out->pcm_device_id < 0) {
6608 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6609 __func__, out->pcm_device_id, out->usecase);
6610 ret = -EINVAL;
6611 goto exit;
6612 }
6613
6614 adjust_mmap_period_count(&out->config, min_size_frames);
6615
Arun Mirpuri5d170872019-03-26 13:21:31 -07006616 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006617 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6618 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6619 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306620 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306621 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6622 out->card_status = CARD_STATUS_OFFLINE;
6623 adev->card_status = CARD_STATUS_OFFLINE;
6624 ret = -EIO;
6625 goto exit;
6626 }
6627
Haynes Mathew George16081042017-05-31 17:16:49 -07006628 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6629 step = "open";
6630 ret = -ENODEV;
6631 goto exit;
6632 }
6633 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6634 if (ret < 0) {
6635 step = "begin";
6636 goto exit;
6637 }
juyuchen626833d2019-06-04 16:48:02 +08006638
6639 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006640 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006641 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006642 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006643 ret = platform_get_mmap_data_fd(adev->platform,
6644 out->pcm_device_id, 0 /*playback*/,
6645 &info->shared_memory_fd,
6646 &mmap_size);
6647 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006648 // Fall back to non exclusive mode
6649 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6650 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006651 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6652 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6653
Arun Mirpuri5d170872019-03-26 13:21:31 -07006654 if (mmap_size < buffer_size) {
6655 step = "mmap";
6656 goto exit;
6657 }
juyuchen626833d2019-06-04 16:48:02 +08006658 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006659 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006660 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006661 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006662
6663 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6664 if (ret < 0) {
6665 step = "commit";
6666 goto exit;
6667 }
6668
Phil Burkfe17efd2019-03-25 10:23:35 -07006669 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6670
Haynes Mathew George16081042017-05-31 17:16:49 -07006671 out->standby = false;
6672 ret = 0;
6673
Arun Mirpuri5d170872019-03-26 13:21:31 -07006674 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006675 __func__, info->shared_memory_address, info->buffer_size_frames);
6676
6677exit:
6678 if (ret != 0) {
6679 if (out->pcm == NULL) {
6680 ALOGE("%s: %s - %d", __func__, step, ret);
6681 } else {
6682 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6683 pcm_close(out->pcm);
6684 out->pcm = NULL;
6685 }
6686 }
6687 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306688 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006689 return ret;
6690}
6691
6692static int out_get_mmap_position(const struct audio_stream_out *stream,
6693 struct audio_mmap_position *position)
6694{
6695 struct stream_out *out = (struct stream_out *)stream;
6696 ALOGVV("%s", __func__);
6697 if (position == NULL) {
6698 return -EINVAL;
6699 }
6700 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006701 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006702 return -ENOSYS;
6703 }
6704 if (out->pcm == NULL) {
6705 return -ENOSYS;
6706 }
6707
6708 struct timespec ts = { 0, 0 };
6709 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6710 if (ret < 0) {
6711 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6712 return ret;
6713 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006714 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6715 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006716 return 0;
6717}
6718
6719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006720/** audio_stream_in implementation **/
6721static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6722{
6723 struct stream_in *in = (struct stream_in *)stream;
6724
6725 return in->config.rate;
6726}
6727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006728static int in_set_sample_rate(struct audio_stream *stream __unused,
6729 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006730{
6731 return -ENOSYS;
6732}
6733
6734static size_t in_get_buffer_size(const struct audio_stream *stream)
6735{
6736 struct stream_in *in = (struct stream_in *)stream;
6737
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006738 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6739 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006740 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6741 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306742 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306743 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006744
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006745 return in->config.period_size * in->af_period_multiplier *
6746 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006747}
6748
6749static uint32_t in_get_channels(const struct audio_stream *stream)
6750{
6751 struct stream_in *in = (struct stream_in *)stream;
6752
6753 return in->channel_mask;
6754}
6755
6756static audio_format_t in_get_format(const struct audio_stream *stream)
6757{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006758 struct stream_in *in = (struct stream_in *)stream;
6759
6760 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006761}
6762
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006763static int in_set_format(struct audio_stream *stream __unused,
6764 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006765{
6766 return -ENOSYS;
6767}
6768
6769static int in_standby(struct audio_stream *stream)
6770{
6771 struct stream_in *in = (struct stream_in *)stream;
6772 struct audio_device *adev = in->dev;
6773 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306774 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6775 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006776 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306777
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006778 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006779 if (!in->standby && in->is_st_session) {
6780 ALOGD("%s: sound trigger pcm stop lab", __func__);
6781 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006782 if (adev->num_va_sessions > 0)
6783 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006784 in->standby = 1;
6785 }
6786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006787 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006788 if (adev->adm_deregister_stream)
6789 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6790
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006791 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006792 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006793 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006794 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006795 voice_extn_compress_voip_close_input_stream(stream);
6796 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006797 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6798 do_stop = in->capture_started;
6799 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006800 if (in->mmap_shared_memory_fd >= 0) {
6801 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6802 __func__, in->mmap_shared_memory_fd);
6803 close(in->mmap_shared_memory_fd);
6804 in->mmap_shared_memory_fd = -1;
6805 }
Zhou Songa8895042016-07-05 17:54:22 +08006806 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306807 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306808 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006809 }
6810
Arun Mirpuri5d170872019-03-26 13:21:31 -07006811 if (in->pcm) {
6812 ATRACE_BEGIN("pcm_in_close");
6813 pcm_close(in->pcm);
6814 ATRACE_END();
6815 in->pcm = NULL;
6816 }
6817
Carter Hsu2e429db2019-05-14 18:50:52 +08006818 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006819 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006820
George Gao3018ede2019-10-23 13:23:00 -07006821 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6822 if (adev->num_va_sessions > 0)
6823 adev->num_va_sessions--;
6824 }
Quinn Malef6050362019-01-30 15:55:40 -08006825
Eric Laurent150dbfe2013-02-27 14:31:02 -08006826 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006827 }
6828 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006829 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006830 return status;
6831}
6832
Aalique Grahame22e49102018-12-18 14:23:57 -08006833static int in_dump(const struct audio_stream *stream,
6834 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835{
Aalique Grahame22e49102018-12-18 14:23:57 -08006836 struct stream_in *in = (struct stream_in *)stream;
6837
6838 // We try to get the lock for consistency,
6839 // but it isn't necessary for these variables.
6840 // If we're not in standby, we may be blocked on a read.
6841 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6842 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6843 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6844 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6845
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006846 char buffer[256]; // for statistics formatting
6847 if (in->start_latency_ms.n > 0) {
6848 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6849 dprintf(fd, " Start latency ms: %s\n", buffer);
6850 }
6851
Aalique Grahame22e49102018-12-18 14:23:57 -08006852 if (locked) {
6853 pthread_mutex_unlock(&in->lock);
6854 }
6855
6856 // dump error info
6857 (void)error_log_dump(
6858 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006860 return 0;
6861}
6862
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306863static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6864{
6865 if (!stream || !parms)
6866 return;
6867
6868 struct stream_in *in = (struct stream_in *)stream;
6869 struct audio_device *adev = in->dev;
6870
6871 card_status_t status;
6872 int card;
6873 if (parse_snd_card_status(parms, &card, &status) < 0)
6874 return;
6875
6876 pthread_mutex_lock(&adev->lock);
6877 bool valid_cb = (card == adev->snd_card);
6878 pthread_mutex_unlock(&adev->lock);
6879
6880 if (!valid_cb)
6881 return;
6882
6883 lock_input_stream(in);
6884 if (in->card_status != status)
6885 in->card_status = status;
6886 pthread_mutex_unlock(&in->lock);
6887
6888 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6889 use_case_table[in->usecase],
6890 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6891
6892 // a better solution would be to report error back to AF and let
6893 // it put the stream to standby
6894 if (status == CARD_STATUS_OFFLINE)
6895 in_standby(&in->stream.common);
6896
6897 return;
6898}
6899
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006900int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006901 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006902 audio_source_t source)
6903{
6904 struct audio_device *adev = in->dev;
6905 int ret = 0;
6906
6907 lock_input_stream(in);
6908 pthread_mutex_lock(&adev->lock);
6909
6910 /* no audio source uses val == 0 */
6911 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6912 in->source = source;
6913 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6914 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6915 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6916 (in->config.rate == 8000 || in->config.rate == 16000 ||
6917 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6918 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6919 ret = voice_extn_compress_voip_open_input_stream(in);
6920 if (ret != 0) {
6921 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6922 __func__, ret);
6923 }
6924 }
6925 }
6926
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006927 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6928 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006929 // Workaround: If routing to an non existing usb device, fail gracefully
6930 // The routing request will otherwise block during 10 second
6931 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006932 struct str_parms *usb_addr =
6933 str_parms_create_str(get_usb_device_address(devices));
6934 if (is_usb_in_device_type(devices) && usb_addr &&
6935 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006936 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6937 ret = -ENOSYS;
6938 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006939 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006940 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006941 if (!in->standby && !in->is_st_session) {
6942 ALOGV("update input routing change");
6943 // inform adm before actual routing to prevent glitches.
6944 if (adev->adm_on_routing_change) {
6945 adev->adm_on_routing_change(adev->adm_data,
6946 in->capture_handle);
6947 ret = select_devices(adev, in->usecase);
6948 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6949 adev->adm_routing_changed = true;
6950 }
6951 }
6952 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006953 if (usb_addr)
6954 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006955 }
6956 pthread_mutex_unlock(&adev->lock);
6957 pthread_mutex_unlock(&in->lock);
6958
6959 ALOGD("%s: exit: status(%d)", __func__, ret);
6960 return ret;
6961}
6962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006963static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6964{
6965 struct stream_in *in = (struct stream_in *)stream;
6966 struct audio_device *adev = in->dev;
6967 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006968 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306969 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006970
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306971 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006972 parms = str_parms_create_str(kvpairs);
6973
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306974 if (!parms)
6975 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006976 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006977 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006978
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306979 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6980 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306981 strlcpy(in->profile, value, sizeof(in->profile));
6982 ALOGV("updating stream profile with value '%s'", in->profile);
6983 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6984 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006985 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306986 in->sample_rate, in->bit_width,
6987 in->profile, &in->app_type_cfg);
6988 }
6989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006990 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006991 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006992
6993 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306994error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306995 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006996}
6997
6998static char* in_get_parameters(const struct audio_stream *stream,
6999 const char *keys)
7000{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007001 struct stream_in *in = (struct stream_in *)stream;
7002 struct str_parms *query = str_parms_create_str(keys);
7003 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007004 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007005
7006 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007007 if (reply) {
7008 str_parms_destroy(reply);
7009 }
7010 if (query) {
7011 str_parms_destroy(query);
7012 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007013 ALOGE("in_get_parameters: failed to create query or reply");
7014 return NULL;
7015 }
7016
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007017 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007018
7019 voice_extn_in_get_parameters(in, query, reply);
7020
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007021 stream_get_parameter_channels(query, reply,
7022 &in->supported_channel_masks[0]);
7023 stream_get_parameter_formats(query, reply,
7024 &in->supported_formats[0]);
7025 stream_get_parameter_rates(query, reply,
7026 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007027 str = str_parms_to_str(reply);
7028 str_parms_destroy(query);
7029 str_parms_destroy(reply);
7030
7031 ALOGV("%s: exit: returns - %s", __func__, str);
7032 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007033}
7034
Aalique Grahame22e49102018-12-18 14:23:57 -08007035static int in_set_gain(struct audio_stream_in *stream,
7036 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007037{
Aalique Grahame22e49102018-12-18 14:23:57 -08007038 struct stream_in *in = (struct stream_in *)stream;
7039 char mixer_ctl_name[128];
7040 struct mixer_ctl *ctl;
7041 int ctl_value;
7042
7043 ALOGV("%s: gain %f", __func__, gain);
7044
7045 if (stream == NULL)
7046 return -EINVAL;
7047
7048 /* in_set_gain() only used to silence MMAP capture for now */
7049 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7050 return -ENOSYS;
7051
7052 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7053
7054 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7055 if (!ctl) {
7056 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7057 __func__, mixer_ctl_name);
7058 return -ENOSYS;
7059 }
7060
7061 if (gain < RECORD_GAIN_MIN)
7062 gain = RECORD_GAIN_MIN;
7063 else if (gain > RECORD_GAIN_MAX)
7064 gain = RECORD_GAIN_MAX;
7065 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7066
7067 mixer_ctl_set_value(ctl, 0, ctl_value);
7068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007069 return 0;
7070}
7071
7072static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7073 size_t bytes)
7074{
7075 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307076
7077 if (in == NULL) {
7078 ALOGE("%s: stream_in ptr is NULL", __func__);
7079 return -EINVAL;
7080 }
7081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007082 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307083 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307084 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007085
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007086 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307087
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007088 if (in->is_st_session) {
7089 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7090 /* Read from sound trigger HAL */
7091 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007092 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007093 if (adev->num_va_sessions < UINT_MAX)
7094 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007095 in->standby = 0;
7096 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007097 pthread_mutex_unlock(&in->lock);
7098 return bytes;
7099 }
7100
Haynes Mathew George16081042017-05-31 17:16:49 -07007101 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7102 ret = -ENOSYS;
7103 goto exit;
7104 }
7105
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007106 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7107 !in->standby && adev->adm_routing_changed) {
7108 ret = -ENOSYS;
7109 goto exit;
7110 }
7111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007112 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007113 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7114
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007115 pthread_mutex_lock(&adev->lock);
7116 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7117 ret = voice_extn_compress_voip_start_input_stream(in);
7118 else
7119 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007120 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7121 if (adev->num_va_sessions < UINT_MAX)
7122 adev->num_va_sessions++;
7123 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007124 pthread_mutex_unlock(&adev->lock);
7125 if (ret != 0) {
7126 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007127 }
7128 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007129
7130 // log startup time in ms.
7131 simple_stats_log(
7132 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307135 /* Avoid read if capture_stopped is set */
7136 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7137 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7138 ret = -EINVAL;
7139 goto exit;
7140 }
7141
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007142 // what's the duration requested by the client?
7143 long ns = 0;
7144
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307145 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007146 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7147 in->config.rate;
7148
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007149 ret = request_in_focus(in, ns);
7150 if (ret != 0)
7151 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007152 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007153
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307154 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307155 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7156 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307157 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007158 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307159 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007160 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007161 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007162 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007163 } else if (audio_extn_ffv_get_stream() == in) {
7164 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307165 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007166 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307167 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7168 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7169 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7170 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307171 ret = -EINVAL;
7172 goto exit;
7173 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307174 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307175 ret = -errno;
7176 }
7177 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307178 /* bytes read is always set to bytes for non compress usecases */
7179 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007180 }
7181
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007182 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007184 /*
Quinn Malef6050362019-01-30 15:55:40 -08007185 * Instead of writing zeroes here, we could trust the hardware to always
7186 * provide zeroes when muted. This is also muted with voice recognition
7187 * usecases so that other clients do not have access to voice recognition
7188 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007189 */
Quinn Malef6050362019-01-30 15:55:40 -08007190 if ((ret == 0 && voice_get_mic_mute(adev) &&
7191 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007192 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7193 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007194 (adev->num_va_sessions &&
7195 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7196 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7197 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007198 memset(buffer, 0, bytes);
7199
7200exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307201 frame_size = audio_stream_in_frame_size(stream);
7202 if (frame_size > 0)
7203 in->frames_read += bytes_read/frame_size;
7204
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007205 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307206 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207 pthread_mutex_unlock(&in->lock);
7208
7209 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307210 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307211 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307212 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307213 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307214 in->standby = true;
7215 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307216 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307217 bytes_read = bytes;
7218 memset(buffer, 0, bytes);
7219 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007220 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007221 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7222 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007223 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307224 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307225 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007226 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307227 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007228}
7229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007230static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007231{
7232 return 0;
7233}
7234
Aalique Grahame22e49102018-12-18 14:23:57 -08007235static int in_get_capture_position(const struct audio_stream_in *stream,
7236 int64_t *frames, int64_t *time)
7237{
7238 if (stream == NULL || frames == NULL || time == NULL) {
7239 return -EINVAL;
7240 }
7241 struct stream_in *in = (struct stream_in *)stream;
7242 int ret = -ENOSYS;
7243
7244 lock_input_stream(in);
7245 // note: ST sessions do not close the alsa pcm driver synchronously
7246 // on standby. Therefore, we may return an error even though the
7247 // pcm stream is still opened.
7248 if (in->standby) {
7249 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7250 "%s stream in standby but pcm not NULL for non ST session", __func__);
7251 goto exit;
7252 }
7253 if (in->pcm) {
7254 struct timespec timestamp;
7255 unsigned int avail;
7256 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7257 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007258 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007259 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007260 ret = 0;
7261 }
7262 }
7263exit:
7264 pthread_mutex_unlock(&in->lock);
7265 return ret;
7266}
7267
Carter Hsu2e429db2019-05-14 18:50:52 +08007268static int in_update_effect_list(bool add, effect_handle_t effect,
7269 struct listnode *head)
7270{
7271 struct listnode *node;
7272 struct in_effect_list *elist = NULL;
7273 struct in_effect_list *target = NULL;
7274 int ret = 0;
7275
7276 if (!head)
7277 return ret;
7278
7279 list_for_each(node, head) {
7280 elist = node_to_item(node, struct in_effect_list, list);
7281 if (elist->handle == effect) {
7282 target = elist;
7283 break;
7284 }
7285 }
7286
7287 if (add) {
7288 if (target) {
7289 ALOGD("effect %p already exist", effect);
7290 return ret;
7291 }
7292
7293 target = (struct in_effect_list *)
7294 calloc(1, sizeof(struct in_effect_list));
7295
7296 if (!target) {
7297 ALOGE("%s:fail to allocate memory", __func__);
7298 return -ENOMEM;
7299 }
7300
7301 target->handle = effect;
7302 list_add_tail(head, &target->list);
7303 } else {
7304 if (target) {
7305 list_remove(&target->list);
7306 free(target);
7307 }
7308 }
7309
7310 return ret;
7311}
7312
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007313static int add_remove_audio_effect(const struct audio_stream *stream,
7314 effect_handle_t effect,
7315 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007316{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007317 struct stream_in *in = (struct stream_in *)stream;
7318 int status = 0;
7319 effect_descriptor_t desc;
7320
7321 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007322 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7323
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007324 if (status != 0)
7325 return status;
7326
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007327 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007328 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007329 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007330 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7331 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007332 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007333
7334 in_update_effect_list(enable, effect, &in->aec_list);
7335 enable = !list_empty(&in->aec_list);
7336 if (enable == in->enable_aec)
7337 goto exit;
7338
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007339 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007340 ALOGD("AEC enable %d", enable);
7341
Aalique Grahame22e49102018-12-18 14:23:57 -08007342 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7343 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7344 in->dev->enable_voicerx = enable;
7345 struct audio_usecase *usecase;
7346 struct listnode *node;
7347 list_for_each(node, &in->dev->usecase_list) {
7348 usecase = node_to_item(node, struct audio_usecase, list);
7349 if (usecase->type == PCM_PLAYBACK)
7350 select_devices(in->dev, usecase->id);
7351 }
7352 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007353 if (!in->standby) {
7354 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7355 select_devices(in->dev, in->usecase);
7356 }
7357
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007358 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007359 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7360
7361 in_update_effect_list(enable, effect, &in->ns_list);
7362 enable = !list_empty(&in->ns_list);
7363 if (enable == in->enable_ns)
7364 goto exit;
7365
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007366 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007367 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007368 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007369 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7370 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007371 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7372 select_devices(in->dev, in->usecase);
7373 } else
7374 select_devices(in->dev, in->usecase);
7375 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007376 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007377exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007378 pthread_mutex_unlock(&in->dev->lock);
7379 pthread_mutex_unlock(&in->lock);
7380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007381 return 0;
7382}
7383
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007384static int in_add_audio_effect(const struct audio_stream *stream,
7385 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007386{
Eric Laurent994a6932013-07-17 11:51:42 -07007387 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007388 return add_remove_audio_effect(stream, effect, true);
7389}
7390
7391static int in_remove_audio_effect(const struct audio_stream *stream,
7392 effect_handle_t effect)
7393{
Eric Laurent994a6932013-07-17 11:51:42 -07007394 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007395 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007396}
7397
Derek Chenf939fb72018-11-13 13:34:41 -08007398streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7399 audio_io_handle_t input)
7400{
7401 struct listnode *node;
7402
7403 list_for_each(node, &dev->active_inputs_list) {
7404 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7405 streams_input_ctxt_t,
7406 list);
7407 if (in_ctxt->input->capture_handle == input) {
7408 return in_ctxt;
7409 }
7410 }
7411 return NULL;
7412}
7413
7414streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7415 audio_io_handle_t output)
7416{
7417 struct listnode *node;
7418
7419 list_for_each(node, &dev->active_outputs_list) {
7420 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7421 streams_output_ctxt_t,
7422 list);
7423 if (out_ctxt->output->handle == output) {
7424 return out_ctxt;
7425 }
7426 }
7427 return NULL;
7428}
7429
Haynes Mathew George16081042017-05-31 17:16:49 -07007430static int in_stop(const struct audio_stream_in* stream)
7431{
7432 struct stream_in *in = (struct stream_in *)stream;
7433 struct audio_device *adev = in->dev;
7434
7435 int ret = -ENOSYS;
7436 ALOGV("%s", __func__);
7437 pthread_mutex_lock(&adev->lock);
7438 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7439 in->capture_started && in->pcm != NULL) {
7440 pcm_stop(in->pcm);
7441 ret = stop_input_stream(in);
7442 in->capture_started = false;
7443 }
7444 pthread_mutex_unlock(&adev->lock);
7445 return ret;
7446}
7447
7448static int in_start(const struct audio_stream_in* stream)
7449{
7450 struct stream_in *in = (struct stream_in *)stream;
7451 struct audio_device *adev = in->dev;
7452 int ret = -ENOSYS;
7453
7454 ALOGV("%s in %p", __func__, in);
7455 pthread_mutex_lock(&adev->lock);
7456 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7457 !in->capture_started && in->pcm != NULL) {
7458 if (!in->capture_started) {
7459 ret = start_input_stream(in);
7460 if (ret == 0) {
7461 in->capture_started = true;
7462 }
7463 }
7464 }
7465 pthread_mutex_unlock(&adev->lock);
7466 return ret;
7467}
7468
Phil Burke0a86d12019-02-16 22:28:11 -08007469// Read offset for the positional timestamp from a persistent vendor property.
7470// This is to workaround apparent inaccuracies in the timing information that
7471// is used by the AAudio timing model. The inaccuracies can cause glitches.
7472static int64_t in_get_mmap_time_offset() {
7473 const int32_t kDefaultOffsetMicros = 0;
7474 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007475 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007476 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7477 return mmap_time_offset_micros * (int64_t)1000;
7478}
7479
Haynes Mathew George16081042017-05-31 17:16:49 -07007480static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7481 int32_t min_size_frames,
7482 struct audio_mmap_buffer_info *info)
7483{
7484 struct stream_in *in = (struct stream_in *)stream;
7485 struct audio_device *adev = in->dev;
7486 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007487 unsigned int offset1 = 0;
7488 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007489 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007490 uint32_t mmap_size = 0;
7491 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007492
7493 pthread_mutex_lock(&adev->lock);
7494 ALOGV("%s in %p", __func__, in);
7495
Sharad Sanglec6f32552018-05-04 16:15:38 +05307496 if (CARD_STATUS_OFFLINE == in->card_status||
7497 CARD_STATUS_OFFLINE == adev->card_status) {
7498 ALOGW("in->card_status or adev->card_status offline, try again");
7499 ret = -EIO;
7500 goto exit;
7501 }
7502
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307503 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007504 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7505 ret = -EINVAL;
7506 goto exit;
7507 }
7508 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7509 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7510 ALOGV("%s in %p", __func__, in);
7511 ret = -ENOSYS;
7512 goto exit;
7513 }
7514 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7515 if (in->pcm_device_id < 0) {
7516 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7517 __func__, in->pcm_device_id, in->usecase);
7518 ret = -EINVAL;
7519 goto exit;
7520 }
7521
7522 adjust_mmap_period_count(&in->config, min_size_frames);
7523
7524 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7525 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7526 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7527 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307528 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307529 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7530 in->card_status = CARD_STATUS_OFFLINE;
7531 adev->card_status = CARD_STATUS_OFFLINE;
7532 ret = -EIO;
7533 goto exit;
7534 }
7535
Haynes Mathew George16081042017-05-31 17:16:49 -07007536 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7537 step = "open";
7538 ret = -ENODEV;
7539 goto exit;
7540 }
7541
7542 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7543 if (ret < 0) {
7544 step = "begin";
7545 goto exit;
7546 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007547
juyuchen626833d2019-06-04 16:48:02 +08007548 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007549 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7550 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7551 info->burst_size_frames = in->config.period_size;
7552 ret = platform_get_mmap_data_fd(adev->platform,
7553 in->pcm_device_id, 1 /*capture*/,
7554 &info->shared_memory_fd,
7555 &mmap_size);
7556 if (ret < 0) {
7557 // Fall back to non exclusive mode
7558 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7559 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007560 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7561 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7562
Arun Mirpuri5d170872019-03-26 13:21:31 -07007563 if (mmap_size < buffer_size) {
7564 step = "mmap";
7565 goto exit;
7566 }
juyuchen626833d2019-06-04 16:48:02 +08007567 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007568 }
7569
7570 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007571
7572 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7573 if (ret < 0) {
7574 step = "commit";
7575 goto exit;
7576 }
7577
Phil Burke0a86d12019-02-16 22:28:11 -08007578 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7579
Haynes Mathew George16081042017-05-31 17:16:49 -07007580 in->standby = false;
7581 ret = 0;
7582
7583 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7584 __func__, info->shared_memory_address, info->buffer_size_frames);
7585
7586exit:
7587 if (ret != 0) {
7588 if (in->pcm == NULL) {
7589 ALOGE("%s: %s - %d", __func__, step, ret);
7590 } else {
7591 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7592 pcm_close(in->pcm);
7593 in->pcm = NULL;
7594 }
7595 }
7596 pthread_mutex_unlock(&adev->lock);
7597 return ret;
7598}
7599
7600static int in_get_mmap_position(const struct audio_stream_in *stream,
7601 struct audio_mmap_position *position)
7602{
7603 struct stream_in *in = (struct stream_in *)stream;
7604 ALOGVV("%s", __func__);
7605 if (position == NULL) {
7606 return -EINVAL;
7607 }
7608 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7609 return -ENOSYS;
7610 }
7611 if (in->pcm == NULL) {
7612 return -ENOSYS;
7613 }
7614 struct timespec ts = { 0, 0 };
7615 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7616 if (ret < 0) {
7617 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7618 return ret;
7619 }
Phil Burke0a86d12019-02-16 22:28:11 -08007620 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7621 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007622 return 0;
7623}
7624
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307625static int in_get_active_microphones(const struct audio_stream_in *stream,
7626 struct audio_microphone_characteristic_t *mic_array,
7627 size_t *mic_count) {
7628 struct stream_in *in = (struct stream_in *)stream;
7629 struct audio_device *adev = in->dev;
7630 ALOGVV("%s", __func__);
7631
7632 lock_input_stream(in);
7633 pthread_mutex_lock(&adev->lock);
7634 int ret = platform_get_active_microphones(adev->platform,
7635 audio_channel_count_from_in_mask(in->channel_mask),
7636 in->usecase, mic_array, mic_count);
7637 pthread_mutex_unlock(&adev->lock);
7638 pthread_mutex_unlock(&in->lock);
7639
7640 return ret;
7641}
7642
7643static int adev_get_microphones(const struct audio_hw_device *dev,
7644 struct audio_microphone_characteristic_t *mic_array,
7645 size_t *mic_count) {
7646 struct audio_device *adev = (struct audio_device *)dev;
7647 ALOGVV("%s", __func__);
7648
7649 pthread_mutex_lock(&adev->lock);
7650 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7651 pthread_mutex_unlock(&adev->lock);
7652
7653 return ret;
7654}
juyuchendb308c22019-01-21 11:57:17 -07007655
7656static void in_update_sink_metadata(struct audio_stream_in *stream,
7657 const struct sink_metadata *sink_metadata) {
7658
7659 if (stream == NULL
7660 || sink_metadata == NULL
7661 || sink_metadata->tracks == NULL) {
7662 return;
7663 }
7664
7665 int error = 0;
7666 struct stream_in *in = (struct stream_in *)stream;
7667 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007668 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007669 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007670
7671 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007672
7673 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007674 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007675
7676 lock_input_stream(in);
7677 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007678 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007679
Zhou Song62ea0282020-03-22 19:53:01 +08007680 is_ha_usecase = adev->ha_proxy_enable ?
7681 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7682 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7683 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007684 && adev->voice_tx_output != NULL) {
7685 /* Use the rx device from afe-proxy record to route voice call because
7686 there is no routing if tx device is on primary hal and rx device
7687 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007688 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007689
7690 if (!voice_is_call_state_active(adev)) {
7691 if (adev->mode == AUDIO_MODE_IN_CALL) {
7692 adev->current_call_output = adev->voice_tx_output;
7693 error = voice_start_call(adev);
7694 if (error != 0)
7695 ALOGE("%s: start voice call failed %d", __func__, error);
7696 }
7697 } else {
7698 adev->current_call_output = adev->voice_tx_output;
7699 voice_update_devices_for_all_voice_usecases(adev);
7700 }
7701 }
7702
7703 pthread_mutex_unlock(&adev->lock);
7704 pthread_mutex_unlock(&in->lock);
7705}
7706
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307707int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007708 audio_io_handle_t handle,
7709 audio_devices_t devices,
7710 audio_output_flags_t flags,
7711 struct audio_config *config,
7712 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007713 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007714{
7715 struct audio_device *adev = (struct audio_device *)dev;
7716 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307717 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007718 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007719 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307720 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007721 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7722 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7723 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7724 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007725 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007726 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7727 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007728 bool force_haptic_path =
7729 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007730 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007731#ifdef AUDIO_GKI_ENABLED
7732 __s32 *generic_dec;
7733#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007734
kunleizdff872d2018-08-20 14:40:33 +08007735 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007736 is_usb_dev = false;
7737 devices = AUDIO_DEVICE_OUT_SPEAKER;
7738 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7739 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007740 if (config->format == AUDIO_FORMAT_DEFAULT)
7741 config->format = AUDIO_FORMAT_PCM_16_BIT;
7742 if (config->sample_rate == 0)
7743 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7744 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7745 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007746 }
7747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007748 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307749
Rahul Sharma99770982019-03-06 17:05:26 +05307750 pthread_mutex_lock(&adev->lock);
7751 if (out_get_stream(adev, handle) != NULL) {
7752 ALOGW("%s, output stream already opened", __func__);
7753 ret = -EEXIST;
7754 }
7755 pthread_mutex_unlock(&adev->lock);
7756 if (ret)
7757 return ret;
7758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007759 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7760
Mingming Yin3a941d42016-02-17 18:08:05 -08007761 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007762 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7763 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307764
7765
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007766 if (!out) {
7767 return -ENOMEM;
7768 }
7769
Haynes Mathew George204045b2015-02-25 20:32:03 -08007770 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007771 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007772 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007773 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007774 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007776 if (devices == AUDIO_DEVICE_NONE)
7777 devices = AUDIO_DEVICE_OUT_SPEAKER;
7778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007779 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007780 list_init(&out->device_list);
7781 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007782 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007783 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007784 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307785 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307786 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7787 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7788 else
7789 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007790 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007791 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007792 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307793 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307794 out->started = 0;
Zhou Song1f93fa52020-11-20 13:57:39 +08007795 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007796 out->hal_output_suspend_supported = 0;
7797 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307798 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307799 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307800 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007801 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007802
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307803 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307804 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007805 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7806
Aalique Grahame22e49102018-12-18 14:23:57 -08007807 if (direct_dev &&
7808 (audio_is_linear_pcm(out->format) ||
7809 config->format == AUDIO_FORMAT_DEFAULT) &&
7810 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7811 audio_format_t req_format = config->format;
7812 audio_channel_mask_t req_channel_mask = config->channel_mask;
7813 uint32_t req_sample_rate = config->sample_rate;
7814
7815 pthread_mutex_lock(&adev->lock);
7816 if (is_hdmi) {
7817 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7818 ret = read_hdmi_sink_caps(out);
7819 if (config->sample_rate == 0)
7820 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7821 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7822 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7823 if (config->format == AUDIO_FORMAT_DEFAULT)
7824 config->format = AUDIO_FORMAT_PCM_16_BIT;
7825 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007826 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7827 &config->format,
7828 &out->supported_formats[0],
7829 MAX_SUPPORTED_FORMATS,
7830 &config->channel_mask,
7831 &out->supported_channel_masks[0],
7832 MAX_SUPPORTED_CHANNEL_MASKS,
7833 &config->sample_rate,
7834 &out->supported_sample_rates[0],
7835 MAX_SUPPORTED_SAMPLE_RATES);
7836 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007837 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007838
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007839 pthread_mutex_unlock(&adev->lock);
7840 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007841 if (ret == -ENOSYS) {
7842 /* ignore and go with default */
7843 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007844 }
7845 // For MMAP NO IRQ, allow conversions in ADSP
7846 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7847 goto error_open;
7848 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007849 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007850 goto error_open;
7851 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007852
7853 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7854 config->sample_rate = req_sample_rate;
7855 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7856 config->channel_mask = req_channel_mask;
7857 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7858 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007859 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007860
7861 out->sample_rate = config->sample_rate;
7862 out->channel_mask = config->channel_mask;
7863 out->format = config->format;
7864 if (is_hdmi) {
7865 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7866 out->config = pcm_config_hdmi_multi;
7867 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7868 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7869 out->config = pcm_config_mmap_playback;
7870 out->stream.start = out_start;
7871 out->stream.stop = out_stop;
7872 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7873 out->stream.get_mmap_position = out_get_mmap_position;
7874 } else {
7875 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7876 out->config = pcm_config_hifi;
7877 }
7878
7879 out->config.rate = out->sample_rate;
7880 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7881 if (is_hdmi) {
7882 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7883 audio_bytes_per_sample(out->format));
7884 }
7885 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007886 }
7887
Derek Chenf6318be2017-06-12 17:16:24 -04007888 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007889 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007890 /* extract car audio stream index */
7891 out->car_audio_stream =
7892 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7893 if (out->car_audio_stream < 0) {
7894 ALOGE("%s: invalid car audio stream %x",
7895 __func__, out->car_audio_stream);
7896 ret = -EINVAL;
7897 goto error_open;
7898 }
Derek Chen5f67a942020-02-24 23:08:13 -08007899 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007900 }
7901
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007902 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007903 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007904 if (!voice_extn_is_compress_voip_supported()) {
7905 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7906 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007907 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307908 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007909 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7910 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007911 out->volume_l = INVALID_OUT_VOLUME;
7912 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007913
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007914 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007915 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007916 uint32_t channel_count =
7917 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307918 out->config.channels = channel_count;
7919
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007920 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7921 out->sample_rate, out->format,
7922 channel_count, false);
7923 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7924 if (frame_size != 0)
7925 out->config.period_size = buffer_size / frame_size;
7926 else
7927 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007928 }
7929 } else {
7930 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7931 voice_extn_compress_voip_is_active(out->dev)) &&
7932 (voice_extn_compress_voip_is_config_supported(config))) {
7933 ret = voice_extn_compress_voip_open_output_stream(out);
7934 if (ret != 0) {
7935 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7936 __func__, ret);
7937 goto error_open;
7938 }
Sujin Panicker19027262019-09-16 18:28:06 +05307939 } else {
7940 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7941 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007942 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007943 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007944 } else if (audio_is_linear_pcm(out->format) &&
7945 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7946 out->channel_mask = config->channel_mask;
7947 out->sample_rate = config->sample_rate;
7948 out->format = config->format;
7949 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7950 // does this change?
7951 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7952 out->config.rate = config->sample_rate;
7953 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7954 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7955 audio_bytes_per_sample(config->format));
7956 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007957 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307958 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307959 pthread_mutex_lock(&adev->lock);
7960 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7961 pthread_mutex_unlock(&adev->lock);
7962
7963 // reject offload during card offline to allow
7964 // fallback to s/w paths
7965 if (offline) {
7966 ret = -ENODEV;
7967 goto error_open;
7968 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007969
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007970 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7971 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7972 ALOGE("%s: Unsupported Offload information", __func__);
7973 ret = -EINVAL;
7974 goto error_open;
7975 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007976
Atul Khare3fa6e542017-08-09 00:56:17 +05307977 if (config->offload_info.format == 0)
7978 config->offload_info.format = config->format;
7979 if (config->offload_info.sample_rate == 0)
7980 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007981
Mingming Yin90310102013-11-13 16:57:00 -08007982 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307983 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007984 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007985 ret = -EINVAL;
7986 goto error_open;
7987 }
7988
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007989 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7990 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7991 (audio_extn_passthru_is_passthrough_stream(out)) &&
7992 !((config->sample_rate == 48000) ||
7993 (config->sample_rate == 96000) ||
7994 (config->sample_rate == 192000))) {
7995 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7996 __func__, config->sample_rate, config->offload_info.format);
7997 ret = -EINVAL;
7998 goto error_open;
7999 }
8000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008001 out->compr_config.codec = (struct snd_codec *)
8002 calloc(1, sizeof(struct snd_codec));
8003
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008004 if (!out->compr_config.codec) {
8005 ret = -ENOMEM;
8006 goto error_open;
8007 }
8008
Dhananjay Kumarac341582017-02-23 23:42:25 +05308009 out->stream.pause = out_pause;
8010 out->stream.resume = out_resume;
8011 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308012 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308013 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008014 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308015 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008016 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308017 } else {
8018 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8019 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008020 }
vivek mehta446c3962015-09-14 10:57:35 -07008021
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308022 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8023 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008024#ifdef AUDIO_GKI_ENABLED
8025 /* out->compr_config.codec->reserved[1] is for flags */
8026 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8027#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308028 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008029#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308030 }
8031
vivek mehta446c3962015-09-14 10:57:35 -07008032 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008033 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008034 config->format == 0 && config->sample_rate == 0 &&
8035 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008036 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008037 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8038 } else {
8039 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8040 ret = -EEXIST;
8041 goto error_open;
8042 }
vivek mehta446c3962015-09-14 10:57:35 -07008043 }
8044
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008045 if (config->offload_info.channel_mask)
8046 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008047 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008048 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008049 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008050 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308051 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008052 ret = -EINVAL;
8053 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008054 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008055
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008056 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008057 out->sample_rate = config->offload_info.sample_rate;
8058
Mingming Yin3ee55c62014-08-04 14:23:35 -07008059 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008060
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308061 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308062 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308063 audio_extn_dolby_send_ddp_endp_params(adev);
8064 audio_extn_dolby_set_dmid(adev);
8065 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008067 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008068 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008069 out->compr_config.codec->bit_rate =
8070 config->offload_info.bit_rate;
8071 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308072 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008073 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308074 /* Update bit width only for non passthrough usecases.
8075 * For passthrough usecases, the output will always be opened @16 bit
8076 */
8077 if (!audio_extn_passthru_is_passthrough_stream(out))
8078 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308079
8080 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008081#ifdef AUDIO_GKI_ENABLED
8082 /* out->compr_config.codec->reserved[1] is for flags */
8083 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8084 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8085#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308086 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8087 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008088#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308089
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008090 /*TODO: Do we need to change it for passthrough */
8091 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008092
Manish Dewangana6fc5442015-08-24 20:30:31 +05308093 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8094 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308095 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308096 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308097 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8098 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308099
8100 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8101 AUDIO_FORMAT_PCM) {
8102
8103 /*Based on platform support, configure appropriate alsa format for corresponding
8104 *hal input format.
8105 */
8106 out->compr_config.codec->format = hal_format_to_alsa(
8107 config->offload_info.format);
8108
Ashish Jain83a6cc22016-06-28 14:34:17 +05308109 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308110 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308111 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308112
Dhananjay Kumarac341582017-02-23 23:42:25 +05308113 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308114 *hal input format and alsa format might differ based on platform support.
8115 */
8116 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308117 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308118
8119 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8120
Deeraj Soman93155a62019-09-30 19:00:37 +05308121 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8122 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8123 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8124 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8125 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308126
Ashish Jainf1eaa582016-05-23 20:54:24 +05308127 /* Check if alsa session is configured with the same format as HAL input format,
8128 * if not then derive correct fragment size needed to accomodate the
8129 * conversion of HAL input format to alsa format.
8130 */
8131 audio_extn_utils_update_direct_pcm_fragment_size(out);
8132
8133 /*if hal input and output fragment size is different this indicates HAL input format is
8134 *not same as the alsa format
8135 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308136 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308137 /*Allocate a buffer to convert input data to the alsa configured format.
8138 *size of convert buffer is equal to the size required to hold one fragment size
8139 *worth of pcm data, this is because flinger does not write more than fragment_size
8140 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308141 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8142 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308143 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8144 ret = -ENOMEM;
8145 goto error_open;
8146 }
8147 }
8148 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8149 out->compr_config.fragment_size =
8150 audio_extn_passthru_get_buffer_size(&config->offload_info);
8151 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8152 } else {
8153 out->compr_config.fragment_size =
8154 platform_get_compress_offload_buffer_size(&config->offload_info);
8155 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8156 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008157
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308158 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8159 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8160 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008161 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8162#ifdef AUDIO_GKI_ENABLED
8163 generic_dec =
8164 &(out->compr_config.codec->options.generic.reserved[1]);
8165 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8166 AUDIO_OUTPUT_BIT_WIDTH;
8167#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308168 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008169#endif
8170 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008171
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308172 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8173 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8174 }
8175
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008176 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8177 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008178
Manish Dewangan69426c82017-01-30 17:35:36 +05308179 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8180 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8181 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8182 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8183 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8184 } else {
8185 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8186 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008187
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308188 memset(&out->channel_map_param, 0,
8189 sizeof(struct audio_out_channel_map_param));
8190
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008191 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308192 out->send_next_track_params = false;
8193 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008194 out->offload_state = OFFLOAD_STATE_IDLE;
8195 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008196 out->writeAt.tv_sec = 0;
8197 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008198
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008199 audio_extn_dts_create_state_notifier_node(out->usecase);
8200
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008201 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8202 __func__, config->offload_info.version,
8203 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308204
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308205 /* Check if DSD audio format is supported in codec
8206 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308207 */
8208
8209 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308210 (!platform_check_codec_dsd_support(adev->platform) ||
8211 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308212 ret = -EINVAL;
8213 goto error_open;
8214 }
8215
Ashish Jain5106d362016-05-11 19:23:33 +05308216 /* Disable gapless if any of the following is true
8217 * passthrough playback
8218 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308219 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308220 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308221 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308222 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008223 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308224 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308225 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308226 check_and_set_gapless_mode(adev, false);
8227 } else
8228 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008229
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308230 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008231 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8232 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308233 if (config->format == AUDIO_FORMAT_DSD) {
8234 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008235#ifdef AUDIO_GKI_ENABLED
8236 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8237 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8238#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308239 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008240#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308241 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008242
8243 create_offload_callback_thread(out);
8244
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008245 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008246 switch (config->sample_rate) {
8247 case 0:
8248 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8249 break;
8250 case 8000:
8251 case 16000:
8252 case 48000:
8253 out->sample_rate = config->sample_rate;
8254 break;
8255 default:
8256 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8257 config->sample_rate);
8258 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8259 ret = -EINVAL;
8260 goto error_open;
8261 }
8262 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8263 switch (config->channel_mask) {
8264 case AUDIO_CHANNEL_NONE:
8265 case AUDIO_CHANNEL_OUT_STEREO:
8266 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8267 break;
8268 default:
8269 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8270 config->channel_mask);
8271 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8272 ret = -EINVAL;
8273 goto error_open;
8274 }
8275 switch (config->format) {
8276 case AUDIO_FORMAT_DEFAULT:
8277 case AUDIO_FORMAT_PCM_16_BIT:
8278 out->format = AUDIO_FORMAT_PCM_16_BIT;
8279 break;
8280 default:
8281 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8282 config->format);
8283 config->format = AUDIO_FORMAT_PCM_16_BIT;
8284 ret = -EINVAL;
8285 goto error_open;
8286 }
8287
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308288 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008289 if (ret != 0) {
8290 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008291 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008292 goto error_open;
8293 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008294 } else if (is_single_device_type_equal(&out->device_list,
8295 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008296 switch (config->sample_rate) {
8297 case 0:
8298 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8299 break;
8300 case 8000:
8301 case 16000:
8302 case 48000:
8303 out->sample_rate = config->sample_rate;
8304 break;
8305 default:
8306 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8307 config->sample_rate);
8308 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8309 ret = -EINVAL;
8310 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008311 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008312 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8313 switch (config->channel_mask) {
8314 case AUDIO_CHANNEL_NONE:
8315 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8316 break;
8317 case AUDIO_CHANNEL_OUT_STEREO:
8318 out->channel_mask = config->channel_mask;
8319 break;
8320 default:
8321 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8322 config->channel_mask);
8323 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8324 ret = -EINVAL;
8325 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008326 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008327 switch (config->format) {
8328 case AUDIO_FORMAT_DEFAULT:
8329 out->format = AUDIO_FORMAT_PCM_16_BIT;
8330 break;
8331 case AUDIO_FORMAT_PCM_16_BIT:
8332 out->format = config->format;
8333 break;
8334 default:
8335 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8336 config->format);
8337 config->format = AUDIO_FORMAT_PCM_16_BIT;
8338 ret = -EINVAL;
8339 break;
8340 }
8341 if (ret != 0)
8342 goto error_open;
8343
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008344 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8345 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008346 out->config.rate = out->sample_rate;
8347 out->config.channels =
8348 audio_channel_count_from_out_mask(out->channel_mask);
8349 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008350 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008351 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308352 unsigned int channels = 0;
8353 /*Update config params to default if not set by the caller*/
8354 if (config->sample_rate == 0)
8355 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8356 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8357 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8358 if (config->format == AUDIO_FORMAT_DEFAULT)
8359 config->format = AUDIO_FORMAT_PCM_16_BIT;
8360
8361 channels = audio_channel_count_from_out_mask(out->channel_mask);
8362
Varun Balaraje49253e2017-07-06 19:48:56 +05308363 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8364 out->usecase = get_interactive_usecase(adev);
8365 out->config = pcm_config_low_latency;
8366 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308367 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008368 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8369 out->flags);
8370 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008371 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8372 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8373 out->config = pcm_config_mmap_playback;
8374 out->stream.start = out_start;
8375 out->stream.stop = out_stop;
8376 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8377 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308378 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8379 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008380 out->hal_output_suspend_supported =
8381 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8382 out->dynamic_pm_qos_config_supported =
8383 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8384 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008385 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8386 } else {
8387 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8388 //the mixer path will be a string similar to "low-latency-playback resume"
8389 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8390 strlcat(out->pm_qos_mixer_path,
8391 " resume", MAX_MIXER_PATH_LEN);
8392 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8393 out->pm_qos_mixer_path);
8394 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308395 out->config = pcm_config_low_latency;
8396 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8397 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8398 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308399 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8400 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8401 if (out->config.period_size <= 0) {
8402 ALOGE("Invalid configuration period size is not valid");
8403 ret = -EINVAL;
8404 goto error_open;
8405 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008406 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8407 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8408 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008409 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8410 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8411 out->config = pcm_config_haptics_audio;
8412 if (force_haptic_path)
8413 adev->haptics_config = pcm_config_haptics_audio;
8414 else
8415 adev->haptics_config = pcm_config_haptics;
8416
Meng Wangd08ce322020-04-02 08:59:20 +08008417 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008418 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8419
8420 if (force_haptic_path) {
8421 out->config.channels = 1;
8422 adev->haptics_config.channels = 1;
8423 } else
8424 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 -08008425 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008426 ret = audio_extn_auto_hal_open_output_stream(out);
8427 if (ret) {
8428 ALOGE("%s: Failed to open output stream for bus device", __func__);
8429 ret = -EINVAL;
8430 goto error_open;
8431 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308432 } else {
8433 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008434 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8435 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308436 }
8437 out->hal_ip_format = format = out->format;
8438 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8439 out->hal_op_format = pcm_format_to_hal(out->config.format);
8440 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8441 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008442 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308443 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308444 if (out->hal_ip_format != out->hal_op_format) {
8445 uint32_t buffer_size = out->config.period_size *
8446 format_to_bitwidth_table[out->hal_op_format] *
8447 out->config.channels;
8448 out->convert_buffer = calloc(1, buffer_size);
8449 if (out->convert_buffer == NULL){
8450 ALOGE("Allocation failed for convert buffer for size %d",
8451 out->compr_config.fragment_size);
8452 ret = -ENOMEM;
8453 goto error_open;
8454 }
8455 ALOGD("Convert buffer allocated of size %d", buffer_size);
8456 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008457 }
8458
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008459 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8460 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308461
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008462 /* TODO remove this hardcoding and check why width is zero*/
8463 if (out->bit_width == 0)
8464 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308465 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008466 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008467 &out->device_list, out->flags,
8468 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308469 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308470 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008471 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008472 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8473 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008474 if(adev->primary_output == NULL)
8475 adev->primary_output = out;
8476 else {
8477 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008478 ret = -EEXIST;
8479 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008480 }
8481 }
8482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008483 /* Check if this usecase is already existing */
8484 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008485 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8486 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008487 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008488 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008489 ret = -EEXIST;
8490 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008491 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 pthread_mutex_unlock(&adev->lock);
8494
8495 out->stream.common.get_sample_rate = out_get_sample_rate;
8496 out->stream.common.set_sample_rate = out_set_sample_rate;
8497 out->stream.common.get_buffer_size = out_get_buffer_size;
8498 out->stream.common.get_channels = out_get_channels;
8499 out->stream.common.get_format = out_get_format;
8500 out->stream.common.set_format = out_set_format;
8501 out->stream.common.standby = out_standby;
8502 out->stream.common.dump = out_dump;
8503 out->stream.common.set_parameters = out_set_parameters;
8504 out->stream.common.get_parameters = out_get_parameters;
8505 out->stream.common.add_audio_effect = out_add_audio_effect;
8506 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8507 out->stream.get_latency = out_get_latency;
8508 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008509#ifdef NO_AUDIO_OUT
8510 out->stream.write = out_write_for_no_output;
8511#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008512 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008513#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008514 out->stream.get_render_position = out_get_render_position;
8515 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008516 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008517
Haynes Mathew George16081042017-05-31 17:16:49 -07008518 if (out->realtime)
8519 out->af_period_multiplier = af_period_multiplier;
8520 else
8521 out->af_period_multiplier = 1;
8522
Andy Hunga1f48fa2019-07-01 18:14:53 -07008523 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008525 out->standby = 1;
Zhou Song1f93fa52020-11-20 13:57:39 +08008526 out->volume_l = PLAYBACK_GAIN_MAX;
8527 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008528 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008529 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008530
8531 config->format = out->stream.common.get_format(&out->stream.common);
8532 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8533 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308534 register_format(out->format, out->supported_formats);
8535 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8536 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008537
Aalique Grahame22e49102018-12-18 14:23:57 -08008538 out->error_log = error_log_create(
8539 ERROR_LOG_ENTRIES,
8540 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8541
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308542 /*
8543 By locking output stream before registering, we allow the callback
8544 to update stream's state only after stream's initial state is set to
8545 adev state.
8546 */
8547 lock_output_stream(out);
8548 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8549 pthread_mutex_lock(&adev->lock);
8550 out->card_status = adev->card_status;
8551 pthread_mutex_unlock(&adev->lock);
8552 pthread_mutex_unlock(&out->lock);
8553
Aalique Grahame22e49102018-12-18 14:23:57 -08008554 stream_app_type_cfg_init(&out->app_type_cfg);
8555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008556 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308557 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008558 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008559
8560 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8561 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8562 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008563 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308564 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008565 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008566 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308567 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8568 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008569 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8570 out->usecase, PCM_PLAYBACK);
8571 hdlr_stream_cfg.flags = out->flags;
8572 hdlr_stream_cfg.type = PCM_PLAYBACK;
8573 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8574 &hdlr_stream_cfg);
8575 if (ret) {
8576 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8577 out->adsp_hdlr_stream_handle = NULL;
8578 }
8579 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308580 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8581 is_direct_passthough, false);
8582 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8583 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008584 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008585 if (ret < 0) {
8586 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8587 out->ip_hdlr_handle = NULL;
8588 }
8589 }
Derek Chenf939fb72018-11-13 13:34:41 -08008590
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008591 ret = io_streams_map_insert(adev, &out->stream.common,
8592 out->handle, AUDIO_PATCH_HANDLE_NONE);
8593 if (ret != 0)
8594 goto error_open;
8595
Derek Chenf939fb72018-11-13 13:34:41 -08008596 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8597 calloc(1, sizeof(streams_output_ctxt_t));
8598 if (out_ctxt == NULL) {
8599 ALOGE("%s fail to allocate output ctxt", __func__);
8600 ret = -ENOMEM;
8601 goto error_open;
8602 }
8603 out_ctxt->output = out;
8604
8605 pthread_mutex_lock(&adev->lock);
8606 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8607 pthread_mutex_unlock(&adev->lock);
8608
Eric Laurent994a6932013-07-17 11:51:42 -07008609 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008610 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008611
8612error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308613 if (out->convert_buffer)
8614 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008615 free(out);
8616 *stream_out = NULL;
8617 ALOGD("%s: exit: ret %d", __func__, ret);
8618 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008619}
8620
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308621void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008622 struct audio_stream_out *stream)
8623{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008624 struct stream_out *out = (struct stream_out *)stream;
8625 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008626 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008627
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008628 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308629
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008630 io_streams_map_remove(adev, out->handle);
8631
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308632 // must deregister from sndmonitor first to prevent races
8633 // between the callback and close_stream
8634 audio_extn_snd_mon_unregister_listener(out);
8635
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008636 /* close adsp hdrl session before standby */
8637 if (out->adsp_hdlr_stream_handle) {
8638 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8639 if (ret)
8640 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8641 out->adsp_hdlr_stream_handle = NULL;
8642 }
8643
Manish Dewangan21a850a2017-08-14 12:03:55 +05308644 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008645 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8646 out->ip_hdlr_handle = NULL;
8647 }
8648
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008649 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308650 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008651 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308652 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308653 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008654 if(ret != 0)
8655 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8656 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008657 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008658 out_standby(&stream->common);
8659
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008660 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008661 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008662 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008663 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008664 if (out->compr_config.codec != NULL)
8665 free(out->compr_config.codec);
8666 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008667
Zhou Song1f93fa52020-11-20 13:57:39 +08008668 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308669
Varun Balaraje49253e2017-07-06 19:48:56 +05308670 if (is_interactive_usecase(out->usecase))
8671 free_interactive_usecase(adev, out->usecase);
8672
Ashish Jain83a6cc22016-06-28 14:34:17 +05308673 if (out->convert_buffer != NULL) {
8674 free(out->convert_buffer);
8675 out->convert_buffer = NULL;
8676 }
8677
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008678 if (adev->voice_tx_output == out)
8679 adev->voice_tx_output = NULL;
8680
Aalique Grahame22e49102018-12-18 14:23:57 -08008681 error_log_destroy(out->error_log);
8682 out->error_log = NULL;
8683
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308684 if (adev->primary_output == out)
8685 adev->primary_output = NULL;
8686
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008687 pthread_cond_destroy(&out->cond);
8688 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008689 pthread_mutex_destroy(&out->pre_lock);
8690 pthread_mutex_destroy(&out->latch_lock);
8691 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008692
8693 pthread_mutex_lock(&adev->lock);
8694 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8695 if (out_ctxt != NULL) {
8696 list_remove(&out_ctxt->list);
8697 free(out_ctxt);
8698 } else {
8699 ALOGW("%s, output stream already closed", __func__);
8700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008701 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008702 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008703 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008704}
8705
8706static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8707{
8708 struct audio_device *adev = (struct audio_device *)dev;
8709 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008710 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008711 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008712 int ret;
8713 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008714 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008715 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008716 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008717
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008718 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008719 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008720
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308721 if (!parms)
8722 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308723
Derek Chen6f293672019-04-01 01:40:24 -07008724 /* notify adev and input/output streams on the snd card status */
8725 adev_snd_mon_cb((void *)adev, parms);
8726
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008727 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8728 if (ret >= 0) {
8729 list_for_each(node, &adev->active_outputs_list) {
8730 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8731 streams_output_ctxt_t,
8732 list);
8733 out_snd_mon_cb((void *)out_ctxt->output, parms);
8734 }
Derek Chen6f293672019-04-01 01:40:24 -07008735
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008736 list_for_each(node, &adev->active_inputs_list) {
8737 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8738 streams_input_ctxt_t,
8739 list);
8740 in_snd_mon_cb((void *)in_ctxt->input, parms);
8741 }
Derek Chen6f293672019-04-01 01:40:24 -07008742 }
8743
Zhou Songd6d71752019-05-21 18:08:51 +08008744 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308745 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8746 if (ret >= 0) {
8747 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008748 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308749 adev->bt_sco_on = true;
Shalini Manjunathac8cd3e92021-02-01 12:23:49 +05308750 /*
8751 * When ever BT_SCO=ON arrives, make sure to route
8752 * all use cases to SCO device, otherwise due to delay in
8753 * BT_SCO=ON and lack of synchronization with create audio patch
8754 * request for SCO device, some times use case not routed properly to
8755 * SCO device
8756 */
8757 struct audio_usecase *usecase;
8758 struct listnode *node;
8759 list_for_each(node, &adev->usecase_list) {
8760 usecase = node_to_item(node, struct audio_usecase, list);
8761 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
8762 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device))) {
8763 ALOGD("BT_SCO ON, switch all in use case to it");
8764 select_devices(adev, usecase->id);
8765 }
8766 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
8767 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE))) {
8768 ALOGD("BT_SCO ON, switch all out use case to it");
8769 select_devices(adev, usecase->id);
8770 }
8771 }
8772 }
8773 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308774 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008775 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008776 }
8777 }
8778
8779 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008780 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008781 if (!strncmp(value, "false", 5) &&
8782 audio_extn_a2dp_source_is_suspended()) {
8783 struct audio_usecase *usecase;
8784 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008785 list_for_each(node, &adev->usecase_list) {
8786 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008787 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008788 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008789 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008790 reassign_device_list(&usecase->stream.in->device_list,
8791 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008792 select_devices(adev, usecase->id);
8793 }
Zhou Songd6d71752019-05-21 18:08:51 +08008794 }
8795 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308796 }
8797
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008798 status = voice_set_parameters(adev, parms);
8799 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008800 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008801
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008802 status = platform_set_parameters(adev->platform, parms);
8803 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008804 goto done;
8805
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008806 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8807 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008808 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008809 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8810 adev->bluetooth_nrec = true;
8811 else
8812 adev->bluetooth_nrec = false;
8813 }
8814
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008815 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8816 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008817 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8818 adev->screen_off = false;
8819 else
8820 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008821 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008822 }
8823
Eric Laurent4b084132018-10-19 17:33:43 -07008824 ret = str_parms_get_int(parms, "rotation", &val);
8825 if (ret >= 0) {
8826 bool reverse_speakers = false;
8827 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8828 switch (val) {
8829 // FIXME: note that the code below assumes that the speakers are in the correct placement
8830 // relative to the user when the device is rotated 90deg from its default rotation. This
8831 // assumption is device-specific, not platform-specific like this code.
8832 case 270:
8833 reverse_speakers = true;
8834 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8835 break;
8836 case 0:
8837 case 180:
8838 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8839 break;
8840 case 90:
8841 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8842 break;
8843 default:
8844 ALOGE("%s: unexpected rotation of %d", __func__, val);
8845 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008846 }
Eric Laurent4b084132018-10-19 17:33:43 -07008847 if (status == 0) {
8848 // check and set swap
8849 // - check if orientation changed and speaker active
8850 // - set rotation and cache the rotation value
8851 adev->camera_orientation =
8852 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8853 if (!audio_extn_is_maxx_audio_enabled())
8854 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8855 }
8856 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008857
Mingming Yin514a8bc2014-07-29 15:22:21 -07008858 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8859 if (ret >= 0) {
8860 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8861 adev->bt_wb_speech_enabled = true;
8862 else
8863 adev->bt_wb_speech_enabled = false;
8864 }
8865
Zhou Song12c29502019-03-16 10:37:18 +08008866 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8867 if (ret >= 0) {
8868 val = atoi(value);
8869 adev->swb_speech_mode = val;
8870 }
8871
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008872 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8873 if (ret >= 0) {
8874 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308875 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008876 if (audio_is_output_device(val) &&
8877 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008878 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008879 platform_get_controller_stream_from_params(parms, &controller, &stream);
8880 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8881 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008882 if (ret < 0) {
8883 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308884 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008885 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008886 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308887 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008888 /*
8889 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8890 * Per AudioPolicyManager, USB device is higher priority than WFD.
8891 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8892 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8893 * starting voice call on USB
8894 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008895 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308896 if (ret >= 0)
8897 audio_extn_usb_add_device(device, atoi(value));
8898
Zhou Song6f862822017-11-06 17:27:57 +08008899 if (!audio_extn_usb_is_tunnel_supported()) {
8900 ALOGV("detected USB connect .. disable proxy");
8901 adev->allow_afe_proxy_usage = false;
8902 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008903 }
8904 }
8905
8906 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8907 if (ret >= 0) {
8908 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308909 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008910 /*
8911 * The HDMI / Displayport disconnect handling has been moved to
8912 * audio extension to ensure that its parameters are not
8913 * invalidated prior to updating sysfs of the disconnect event
8914 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8915 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308916 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008917 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308918 if (ret >= 0)
8919 audio_extn_usb_remove_device(device, atoi(value));
8920
Zhou Song6f862822017-11-06 17:27:57 +08008921 if (!audio_extn_usb_is_tunnel_supported()) {
8922 ALOGV("detected USB disconnect .. enable proxy");
8923 adev->allow_afe_proxy_usage = true;
8924 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008925 }
8926 }
8927
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008928 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008929
8930 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008931 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308932 struct audio_usecase *usecase;
8933 struct listnode *node;
8934 list_for_each(node, &adev->usecase_list) {
8935 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008936 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8937 continue;
8938
8939 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308940 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308941 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308942 ALOGD("Switching to speaker and muting the stream before select_devices");
8943 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308944 //force device switch to re configure encoder
8945 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308946 ALOGD("Unmuting the stream after select_devices");
Zhou Song1f93fa52020-11-20 13:57:39 +08008947 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308948 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308949 break;
Zhou Song9ebf6792020-09-23 22:49:01 +08008950 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008951 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08008952 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008953 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8954 reassign_device_list(&usecase->stream.out->device_list,
8955 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8956 check_a2dp_restore_l(adev, usecase->stream.out, true);
8957 break;
8958 }
8959 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308960 }
8961 }
8962 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008963
8964 //handle vr audio setparam
8965 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8966 value, sizeof(value));
8967 if (ret >= 0) {
8968 ALOGI("Setting vr mode to be %s", value);
8969 if (!strncmp(value, "true", 4)) {
8970 adev->vr_audio_mode_enabled = true;
8971 ALOGI("Setting vr mode to true");
8972 } else if (!strncmp(value, "false", 5)) {
8973 adev->vr_audio_mode_enabled = false;
8974 ALOGI("Setting vr mode to false");
8975 } else {
8976 ALOGI("wrong vr mode set");
8977 }
8978 }
8979
Eric Laurent4b084132018-10-19 17:33:43 -07008980 //FIXME: to be replaced by proper video capture properties API
8981 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8982 if (ret >= 0) {
8983 int camera_facing = CAMERA_FACING_BACK;
8984 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8985 camera_facing = CAMERA_FACING_FRONT;
8986 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8987 camera_facing = CAMERA_FACING_BACK;
8988 else {
8989 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8990 goto done;
8991 }
8992 adev->camera_orientation =
8993 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8994 struct audio_usecase *usecase;
8995 struct listnode *node;
8996 list_for_each(node, &adev->usecase_list) {
8997 usecase = node_to_item(node, struct audio_usecase, list);
8998 struct stream_in *in = usecase->stream.in;
8999 if (usecase->type == PCM_CAPTURE && in != NULL &&
9000 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9001 select_devices(adev, in->usecase);
9002 }
9003 }
9004 }
9005
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309006 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009007done:
9008 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009009 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309010error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009011 ALOGV("%s: exit with code(%d)", __func__, status);
9012 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009013}
9014
9015static char* adev_get_parameters(const struct audio_hw_device *dev,
9016 const char *keys)
9017{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309018 ALOGD("%s:%s", __func__, keys);
9019
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009020 struct audio_device *adev = (struct audio_device *)dev;
9021 struct str_parms *reply = str_parms_create();
9022 struct str_parms *query = str_parms_create_str(keys);
9023 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309024 char value[256] = {0};
9025 int ret = 0;
9026
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009027 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009028 if (reply) {
9029 str_parms_destroy(reply);
9030 }
9031 if (query) {
9032 str_parms_destroy(query);
9033 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009034 ALOGE("adev_get_parameters: failed to create query or reply");
9035 return NULL;
9036 }
9037
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009038 //handle vr audio getparam
9039
9040 ret = str_parms_get_str(query,
9041 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9042 value, sizeof(value));
9043
9044 if (ret >= 0) {
9045 bool vr_audio_enabled = false;
9046 pthread_mutex_lock(&adev->lock);
9047 vr_audio_enabled = adev->vr_audio_mode_enabled;
9048 pthread_mutex_unlock(&adev->lock);
9049
9050 ALOGI("getting vr mode to %d", vr_audio_enabled);
9051
9052 if (vr_audio_enabled) {
9053 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9054 "true");
9055 goto exit;
9056 } else {
9057 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9058 "false");
9059 goto exit;
9060 }
9061 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009062
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009063 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009064 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009065 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009066 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009067 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009068 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309069 pthread_mutex_unlock(&adev->lock);
9070
Naresh Tannirud7205b62014-06-20 02:54:48 +05309071exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009072 str = str_parms_to_str(reply);
9073 str_parms_destroy(query);
9074 str_parms_destroy(reply);
9075
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309076 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009077 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009078}
9079
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009080static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009081{
9082 return 0;
9083}
9084
9085static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9086{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009087 int ret;
9088 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009089
9090 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9091
Haynes Mathew George5191a852013-09-11 14:19:36 -07009092 pthread_mutex_lock(&adev->lock);
9093 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009094 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009095 pthread_mutex_unlock(&adev->lock);
9096 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009097}
9098
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009099static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9100 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009101{
9102 return -ENOSYS;
9103}
9104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009105static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9106 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009107{
9108 return -ENOSYS;
9109}
9110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009111static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9112 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113{
9114 return -ENOSYS;
9115}
9116
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009117static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9118 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009119{
9120 return -ENOSYS;
9121}
9122
9123static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9124{
9125 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009126 struct listnode *node;
9127 struct audio_usecase *usecase = NULL;
9128 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009130 pthread_mutex_lock(&adev->lock);
9131 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309132 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9133 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009134 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009135 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309136 adev->current_call_output = adev->primary_output;
9137 voice_start_call(adev);
9138 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009139 (mode == AUDIO_MODE_NORMAL ||
9140 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009141 list_for_each(node, &adev->usecase_list) {
9142 usecase = node_to_item(node, struct audio_usecase, list);
9143 if (usecase->type == VOICE_CALL)
9144 break;
9145 }
9146 if (usecase &&
9147 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9148 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9149 true);
9150 if (ret != 0) {
9151 /* default service interval was successfully updated,
9152 reopen USB backend with new service interval */
9153 check_usecases_codec_backend(adev,
9154 usecase,
9155 usecase->out_snd_device);
9156 }
9157 }
9158
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009159 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009160 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009161 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009162 // restore device for other active usecases after stop call
9163 list_for_each(node, &adev->usecase_list) {
9164 usecase = node_to_item(node, struct audio_usecase, list);
9165 select_devices(adev, usecase->id);
9166 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009168 }
9169 pthread_mutex_unlock(&adev->lock);
9170 return 0;
9171}
9172
9173static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9174{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009175 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009176 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009177
9178 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009179 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009180 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009181
Derek Chend2530072014-11-24 12:39:14 -08009182 if (adev->ext_hw_plugin)
9183 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009184
9185 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009186 pthread_mutex_unlock(&adev->lock);
9187
9188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009189}
9190
9191static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9192{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009193 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009194 return 0;
9195}
9196
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009197static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009198 const struct audio_config *config)
9199{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009200 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009201
Aalique Grahame22e49102018-12-18 14:23:57 -08009202 /* Don't know if USB HIFI in this context so use true to be conservative */
9203 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9204 true /*is_usb_hifi */) != 0)
9205 return 0;
9206
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009207 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9208 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009209}
9210
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009211static bool adev_input_allow_hifi_record(struct audio_device *adev,
9212 audio_devices_t devices,
9213 audio_input_flags_t flags,
9214 audio_source_t source) {
9215 const bool allowed = true;
9216
9217 if (!audio_is_usb_in_device(devices))
9218 return !allowed;
9219
9220 switch (flags) {
9221 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009222 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009223 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9224 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009225 default:
9226 return !allowed;
9227 }
9228
9229 switch (source) {
9230 case AUDIO_SOURCE_DEFAULT:
9231 case AUDIO_SOURCE_MIC:
9232 case AUDIO_SOURCE_UNPROCESSED:
9233 break;
9234 default:
9235 return !allowed;
9236 }
9237
9238 switch (adev->mode) {
9239 case 0:
9240 break;
9241 default:
9242 return !allowed;
9243 }
9244
9245 return allowed;
9246}
9247
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009248static int adev_update_voice_comm_input_stream(struct stream_in *in,
9249 struct audio_config *config)
9250{
9251 bool valid_rate = (config->sample_rate == 8000 ||
9252 config->sample_rate == 16000 ||
9253 config->sample_rate == 32000 ||
9254 config->sample_rate == 48000);
9255 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9256
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009257 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009258 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009259 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9260 in->config = default_pcm_config_voip_copp;
9261 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9262 DEFAULT_VOIP_BUF_DURATION_MS,
9263 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009264 } else {
9265 ALOGW("%s No valid input in voip, use defaults"
9266 "sample rate %u, channel mask 0x%X",
9267 __func__, config->sample_rate, in->channel_mask);
9268 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009269 in->config.rate = config->sample_rate;
9270 in->sample_rate = config->sample_rate;
9271 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009272 //XXX needed for voice_extn_compress_voip_open_input_stream
9273 in->config.rate = config->sample_rate;
9274 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309275 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009276 voice_extn_compress_voip_is_active(in->dev)) &&
9277 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9278 valid_rate && valid_ch) {
9279 voice_extn_compress_voip_open_input_stream(in);
9280 // update rate entries to match config from AF
9281 in->config.rate = config->sample_rate;
9282 in->sample_rate = config->sample_rate;
9283 } else {
9284 ALOGW("%s compress voip not active, use defaults", __func__);
9285 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009286 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009287 return 0;
9288}
9289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009290static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009291 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009292 audio_devices_t devices,
9293 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009294 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309295 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009296 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009297 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009298{
9299 struct audio_device *adev = (struct audio_device *)dev;
9300 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009301 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009302 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009303 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309304 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009305 bool is_usb_dev = audio_is_usb_in_device(devices);
9306 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9307 devices,
9308 flags,
9309 source);
Andy Hung94320602018-10-29 18:31:12 -07009310 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9311 " sample_rate %u, channel_mask %#x, format %#x",
9312 __func__, flags, is_usb_dev, may_use_hifi_record,
9313 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309314
kunleizdff872d2018-08-20 14:40:33 +08009315 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009316 is_usb_dev = false;
9317 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9318 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9319 __func__, devices);
9320 }
9321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009322 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009323
9324 if (!(is_usb_dev && may_use_hifi_record)) {
9325 if (config->sample_rate == 0)
9326 config->sample_rate = 48000;
9327 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9328 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9329 if (config->format == AUDIO_FORMAT_DEFAULT)
9330 config->format = AUDIO_FORMAT_PCM_16_BIT;
9331
9332 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9333
Aalique Grahame22e49102018-12-18 14:23:57 -08009334 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9335 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009336 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309337 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009338
Rahul Sharma99770982019-03-06 17:05:26 +05309339 pthread_mutex_lock(&adev->lock);
9340 if (in_get_stream(adev, handle) != NULL) {
9341 ALOGW("%s, input stream already opened", __func__);
9342 ret = -EEXIST;
9343 }
9344 pthread_mutex_unlock(&adev->lock);
9345 if (ret)
9346 return ret;
9347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009348 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009349
9350 if (!in) {
9351 ALOGE("failed to allocate input stream");
9352 return -ENOMEM;
9353 }
9354
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309355 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309356 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9357 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009358 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009359 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009361 in->stream.common.get_sample_rate = in_get_sample_rate;
9362 in->stream.common.set_sample_rate = in_set_sample_rate;
9363 in->stream.common.get_buffer_size = in_get_buffer_size;
9364 in->stream.common.get_channels = in_get_channels;
9365 in->stream.common.get_format = in_get_format;
9366 in->stream.common.set_format = in_set_format;
9367 in->stream.common.standby = in_standby;
9368 in->stream.common.dump = in_dump;
9369 in->stream.common.set_parameters = in_set_parameters;
9370 in->stream.common.get_parameters = in_get_parameters;
9371 in->stream.common.add_audio_effect = in_add_audio_effect;
9372 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9373 in->stream.set_gain = in_set_gain;
9374 in->stream.read = in_read;
9375 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009376 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309377 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009378 in->stream.set_microphone_direction = in_set_microphone_direction;
9379 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009380 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009381
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009382 list_init(&in->device_list);
9383 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009384 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009385 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009386 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009387 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009388 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009389 in->bit_width = 16;
9390 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009391 in->direction = MIC_DIRECTION_UNSPECIFIED;
9392 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009393 list_init(&in->aec_list);
9394 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009395 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009396
Andy Hung94320602018-10-29 18:31:12 -07009397 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009398 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9399 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9400 /* Force channel config requested to mono if incall
9401 record is being requested for only uplink/downlink */
9402 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9403 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9404 ret = -EINVAL;
9405 goto err_open;
9406 }
9407 }
9408
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009409 if (is_usb_dev && may_use_hifi_record) {
9410 /* HiFi record selects an appropriate format, channel, rate combo
9411 depending on sink capabilities*/
9412 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9413 &config->format,
9414 &in->supported_formats[0],
9415 MAX_SUPPORTED_FORMATS,
9416 &config->channel_mask,
9417 &in->supported_channel_masks[0],
9418 MAX_SUPPORTED_CHANNEL_MASKS,
9419 &config->sample_rate,
9420 &in->supported_sample_rates[0],
9421 MAX_SUPPORTED_SAMPLE_RATES);
9422 if (ret != 0) {
9423 ret = -EINVAL;
9424 goto err_open;
9425 }
9426 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009427 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309428 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309429 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9430 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9431 in->config.format = PCM_FORMAT_S32_LE;
9432 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309433 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9434 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9435 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9436 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9437 bool ret_error = false;
9438 in->bit_width = 24;
9439 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9440 from HAL is 24_packed and 8_24
9441 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9442 24_packed return error indicating supported format is 24_packed
9443 *> In case of any other source requesting 24 bit or float return error
9444 indicating format supported is 16 bit only.
9445
9446 on error flinger will retry with supported format passed
9447 */
9448 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9449 (source != AUDIO_SOURCE_CAMCORDER)) {
9450 config->format = AUDIO_FORMAT_PCM_16_BIT;
9451 if (config->sample_rate > 48000)
9452 config->sample_rate = 48000;
9453 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009454 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9455 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309456 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9457 ret_error = true;
9458 }
9459
9460 if (ret_error) {
9461 ret = -EINVAL;
9462 goto err_open;
9463 }
9464 }
9465
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009466 in->channel_mask = config->channel_mask;
9467 in->format = config->format;
9468
9469 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309470
9471 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9472 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9473 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9474 else {
9475 ret = -EINVAL;
9476 goto err_open;
9477 }
9478 }
9479
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009480 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309481 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9482 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009483 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9484 is_low_latency = true;
9485#if LOW_LATENCY_CAPTURE_USE_CASE
9486 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9487#endif
9488 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009489 if (!in->realtime) {
9490 in->config = pcm_config_audio_capture;
9491 frame_size = audio_stream_in_frame_size(&in->stream);
9492 buffer_size = get_input_buffer_size(config->sample_rate,
9493 config->format,
9494 channel_count,
9495 is_low_latency);
9496 in->config.period_size = buffer_size / frame_size;
9497 in->config.rate = config->sample_rate;
9498 in->af_period_multiplier = 1;
9499 } else {
9500 // period size is left untouched for rt mode playback
9501 in->config = pcm_config_audio_capture_rt;
9502 in->af_period_multiplier = af_period_multiplier;
9503 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009504 }
9505
9506 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9507 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9508 in->realtime = 0;
9509 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9510 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009511 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009512 in->stream.start = in_start;
9513 in->stream.stop = in_stop;
9514 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9515 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009516 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009517 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009518 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9519 in->config = pcm_config_audio_capture;
9520 frame_size = audio_stream_in_frame_size(&in->stream);
9521 buffer_size = get_input_buffer_size(config->sample_rate,
9522 config->format,
9523 channel_count,
9524 false /*is_low_latency*/);
9525 in->config.period_size = buffer_size / frame_size;
9526 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009527 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009528 switch (config->format) {
9529 case AUDIO_FORMAT_PCM_32_BIT:
9530 in->bit_width = 32;
9531 break;
9532 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9533 case AUDIO_FORMAT_PCM_8_24_BIT:
9534 in->bit_width = 24;
9535 break;
9536 default:
9537 in->bit_width = 16;
9538 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009539 } else if (is_single_device_type_equal(&in->device_list,
9540 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9541 is_single_device_type_equal(&in->device_list,
9542 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009543 if (config->sample_rate == 0)
9544 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9545 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9546 config->sample_rate != 8000) {
9547 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9548 ret = -EINVAL;
9549 goto err_open;
9550 }
9551 if (config->format == AUDIO_FORMAT_DEFAULT)
9552 config->format = AUDIO_FORMAT_PCM_16_BIT;
9553 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9554 config->format = AUDIO_FORMAT_PCM_16_BIT;
9555 ret = -EINVAL;
9556 goto err_open;
9557 }
9558
9559 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009560 if (adev->ha_proxy_enable &&
9561 is_single_device_type_equal(&in->device_list,
9562 AUDIO_DEVICE_IN_TELEPHONY_RX))
9563 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009564 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009565 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009566 in->af_period_multiplier = 1;
9567 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaabdf7482020-01-03 15:00:14 +05309568 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009569 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9570 (config->sample_rate == 8000 ||
9571 config->sample_rate == 16000 ||
9572 config->sample_rate == 32000 ||
9573 config->sample_rate == 48000) &&
9574 channel_count == 1) {
9575 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9576 in->config = pcm_config_audio_capture;
9577 frame_size = audio_stream_in_frame_size(&in->stream);
9578 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9579 config->sample_rate,
9580 config->format,
9581 channel_count, false /*is_low_latency*/);
9582 in->config.period_size = buffer_size / frame_size;
9583 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9584 in->config.rate = config->sample_rate;
9585 in->af_period_multiplier = 1;
Mingshu Pang7b59b5e2021-01-14 16:19:10 +08009586 } else if (in->realtime) {
9587 in->config = pcm_config_audio_capture_rt;
9588 in->config.format = pcm_format_from_audio_format(config->format);
9589 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009590 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309591 int ret_val;
9592 pthread_mutex_lock(&adev->lock);
9593 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9594 in, config, &channel_mask_updated);
9595 pthread_mutex_unlock(&adev->lock);
9596
9597 if (!ret_val) {
9598 if (channel_mask_updated == true) {
9599 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9600 __func__, config->channel_mask);
9601 ret = -EINVAL;
9602 goto err_open;
9603 }
9604 ALOGD("%s: created multi-channel session succesfully",__func__);
9605 } else if (audio_extn_compr_cap_enabled() &&
9606 audio_extn_compr_cap_format_supported(config->format) &&
9607 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9608 audio_extn_compr_cap_init(in);
9609 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309610 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309611 if (ret)
9612 goto err_open;
9613 } else {
9614 in->config = pcm_config_audio_capture;
9615 in->config.rate = config->sample_rate;
9616 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309617 in->format = config->format;
9618 frame_size = audio_stream_in_frame_size(&in->stream);
9619 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009620 config->format,
9621 channel_count,
9622 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009623 /* prevent division-by-zero */
9624 if (frame_size == 0) {
9625 ALOGE("%s: Error frame_size==0", __func__);
9626 ret = -EINVAL;
9627 goto err_open;
9628 }
9629
Revathi Uddarajud2634032017-12-07 14:42:34 +05309630 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009631 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009632
Revathi Uddarajud2634032017-12-07 14:42:34 +05309633 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9634 /* optionally use VOIP usecase depending on config(s) */
9635 ret = adev_update_voice_comm_input_stream(in, config);
9636 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009637
Revathi Uddarajud2634032017-12-07 14:42:34 +05309638 if (ret) {
9639 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9640 goto err_open;
9641 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009642 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309643
9644 /* assign concurrent capture usecase if record has to caried out from
9645 * actual hardware input source */
9646 if (audio_extn_is_concurrent_capture_enabled() &&
9647 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309648 /* Acquire lock to avoid two concurrent use cases initialized to
9649 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009650
Samyak Jainc37062f2019-04-25 18:41:06 +05309651 if (in->usecase == USECASE_AUDIO_RECORD) {
9652 pthread_mutex_lock(&adev->lock);
9653 if (!(adev->pcm_record_uc_state)) {
9654 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9655 adev->pcm_record_uc_state = 1;
9656 pthread_mutex_unlock(&adev->lock);
9657 } else {
9658 pthread_mutex_unlock(&adev->lock);
9659 /* Assign compress record use case for second record */
9660 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9661 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9662 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9663 if (audio_extn_cin_applicable_stream(in)) {
9664 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309665 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309666 if (ret)
9667 goto err_open;
9668 }
9669 }
9670 }
kunleiz28c73e72019-03-27 17:24:04 +08009671 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009672 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309673 if (audio_extn_ssr_get_stream() != in)
9674 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009675
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009676 in->sample_rate = in->config.rate;
9677
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309678 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9679 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009680 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009681 in->sample_rate, in->bit_width,
9682 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309683 register_format(in->format, in->supported_formats);
9684 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9685 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309686
Aalique Grahame22e49102018-12-18 14:23:57 -08009687 in->error_log = error_log_create(
9688 ERROR_LOG_ENTRIES,
9689 1000000000 /* aggregate consecutive identical errors within one second */);
9690
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009691 /* This stream could be for sound trigger lab,
9692 get sound trigger pcm if present */
9693 audio_extn_sound_trigger_check_and_get_session(in);
9694
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309695 lock_input_stream(in);
9696 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9697 pthread_mutex_lock(&adev->lock);
9698 in->card_status = adev->card_status;
9699 pthread_mutex_unlock(&adev->lock);
9700 pthread_mutex_unlock(&in->lock);
9701
Aalique Grahame22e49102018-12-18 14:23:57 -08009702 stream_app_type_cfg_init(&in->app_type_cfg);
9703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009704 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009705
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009706 ret = io_streams_map_insert(adev, &in->stream.common,
9707 handle, AUDIO_PATCH_HANDLE_NONE);
9708 if (ret != 0)
9709 goto err_open;
9710
Derek Chenf939fb72018-11-13 13:34:41 -08009711 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9712 calloc(1, sizeof(streams_input_ctxt_t));
9713 if (in_ctxt == NULL) {
9714 ALOGE("%s fail to allocate input ctxt", __func__);
9715 ret = -ENOMEM;
9716 goto err_open;
9717 }
9718 in_ctxt->input = in;
9719
9720 pthread_mutex_lock(&adev->lock);
9721 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9722 pthread_mutex_unlock(&adev->lock);
9723
Eric Laurent994a6932013-07-17 11:51:42 -07009724 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009725 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009726
9727err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309728 if (in->usecase == USECASE_AUDIO_RECORD) {
9729 pthread_mutex_lock(&adev->lock);
9730 adev->pcm_record_uc_state = 0;
9731 pthread_mutex_unlock(&adev->lock);
9732 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009733 free(in);
9734 *stream_in = NULL;
9735 return ret;
9736}
9737
9738static void adev_close_input_stream(struct audio_hw_device *dev,
9739 struct audio_stream_in *stream)
9740{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009741 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009742 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009743 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309744
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309745 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009746
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009747 if (in == NULL) {
9748 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9749 return;
9750 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009751 io_streams_map_remove(adev, in->capture_handle);
9752
kunleiz70e57612018-12-28 17:50:23 +08009753 /* must deregister from sndmonitor first to prevent races
9754 * between the callback and close_stream
9755 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309756 audio_extn_snd_mon_unregister_listener(stream);
9757
kunleiz70e57612018-12-28 17:50:23 +08009758 /* Disable echo reference if there are no active input, hfp call
9759 * and sound trigger while closing input stream
9760 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009761 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009762 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009763 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9764 struct listnode out_devices;
9765 list_init(&out_devices);
9766 platform_set_echo_reference(adev, false, &out_devices);
9767 } else
kunleiz70e57612018-12-28 17:50:23 +08009768 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309769
Weiyin Jiang2995f662019-04-17 14:25:12 +08009770 error_log_destroy(in->error_log);
9771 in->error_log = NULL;
9772
Pallavid7c7a272018-01-16 11:22:55 +05309773
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009774 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309775 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009776 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309777 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009778 if (ret != 0)
9779 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9780 __func__, ret);
9781 } else
9782 in_standby(&stream->common);
9783
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009784 pthread_mutex_destroy(&in->lock);
9785 pthread_mutex_destroy(&in->pre_lock);
9786
Revathi Uddarajud2634032017-12-07 14:42:34 +05309787 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309788 if (in->usecase == USECASE_AUDIO_RECORD) {
9789 adev->pcm_record_uc_state = 0;
9790 }
9791
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009792 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9793 adev->enable_voicerx = false;
9794 }
9795
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009796 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009797 audio_extn_ssr_deinit();
9798 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009799
Garmond Leunge2433c32017-09-28 21:51:22 -07009800 if (audio_extn_ffv_get_stream() == in) {
9801 audio_extn_ffv_stream_deinit();
9802 }
9803
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309804 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009805 audio_extn_compr_cap_format_supported(in->config.format))
9806 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309807
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309808 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309809 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009810
Mingming Yinfd7607b2016-01-22 12:48:44 -08009811 if (in->is_st_session) {
9812 ALOGV("%s: sound trigger pcm stop lab", __func__);
9813 audio_extn_sound_trigger_stop_lab(in);
9814 }
Derek Chenf939fb72018-11-13 13:34:41 -08009815 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9816 if (in_ctxt != NULL) {
9817 list_remove(&in_ctxt->list);
9818 free(in_ctxt);
9819 } else {
9820 ALOGW("%s, input stream already closed", __func__);
9821 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009822 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309823 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009824 return;
9825}
9826
Aalique Grahame22e49102018-12-18 14:23:57 -08009827/* verifies input and output devices and their capabilities.
9828 *
9829 * This verification is required when enabling extended bit-depth or
9830 * sampling rates, as not all qcom products support it.
9831 *
9832 * Suitable for calling only on initialization such as adev_open().
9833 * It fills the audio_device use_case_table[] array.
9834 *
9835 * Has a side-effect that it needs to configure audio routing / devices
9836 * in order to power up the devices and read the device parameters.
9837 * It does not acquire any hw device lock. Should restore the devices
9838 * back to "normal state" upon completion.
9839 */
9840static int adev_verify_devices(struct audio_device *adev)
9841{
9842 /* enumeration is a bit difficult because one really wants to pull
9843 * the use_case, device id, etc from the hidden pcm_device_table[].
9844 * In this case there are the following use cases and device ids.
9845 *
9846 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9847 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9848 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9849 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9850 * [USECASE_AUDIO_RECORD] = {0, 0},
9851 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9852 * [USECASE_VOICE_CALL] = {2, 2},
9853 *
9854 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9855 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9856 */
9857
9858 /* should be the usecases enabled in adev_open_input_stream() */
9859 static const int test_in_usecases[] = {
9860 USECASE_AUDIO_RECORD,
9861 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9862 };
9863 /* should be the usecases enabled in adev_open_output_stream()*/
9864 static const int test_out_usecases[] = {
9865 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9866 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9867 };
9868 static const usecase_type_t usecase_type_by_dir[] = {
9869 PCM_PLAYBACK,
9870 PCM_CAPTURE,
9871 };
9872 static const unsigned flags_by_dir[] = {
9873 PCM_OUT,
9874 PCM_IN,
9875 };
9876
9877 size_t i;
9878 unsigned dir;
9879 const unsigned card_id = adev->snd_card;
9880
9881 for (dir = 0; dir < 2; ++dir) {
9882 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9883 const unsigned flags_dir = flags_by_dir[dir];
9884 const size_t testsize =
9885 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9886 const int *testcases =
9887 dir ? test_in_usecases : test_out_usecases;
9888 const audio_devices_t audio_device =
9889 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9890
9891 for (i = 0; i < testsize; ++i) {
9892 const audio_usecase_t audio_usecase = testcases[i];
9893 int device_id;
9894 struct pcm_params **pparams;
9895 struct stream_out out;
9896 struct stream_in in;
9897 struct audio_usecase uc_info;
9898 int retval;
9899
9900 pparams = &adev->use_case_table[audio_usecase];
9901 pcm_params_free(*pparams); /* can accept null input */
9902 *pparams = NULL;
9903
9904 /* find the device ID for the use case (signed, for error) */
9905 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9906 if (device_id < 0)
9907 continue;
9908
9909 /* prepare structures for device probing */
9910 memset(&uc_info, 0, sizeof(uc_info));
9911 uc_info.id = audio_usecase;
9912 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009913 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009914 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009915 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009916 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009917 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009918 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9919 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009920 }
9921 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009922 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009923 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009924 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009925 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009926 uc_info.in_snd_device = SND_DEVICE_NONE;
9927 uc_info.out_snd_device = SND_DEVICE_NONE;
9928 list_add_tail(&adev->usecase_list, &uc_info.list);
9929
9930 /* select device - similar to start_(in/out)put_stream() */
9931 retval = select_devices(adev, audio_usecase);
9932 if (retval >= 0) {
9933 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9934#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009935 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009936 if (*pparams) {
9937 ALOGV("%s: (%s) card %d device %d", __func__,
9938 dir ? "input" : "output", card_id, device_id);
9939 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9940 } else {
9941 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9942 }
9943#endif
9944 }
9945
9946 /* deselect device - similar to stop_(in/out)put_stream() */
9947 /* 1. Get and set stream specific mixer controls */
9948 retval = disable_audio_route(adev, &uc_info);
9949 /* 2. Disable the rx device */
9950 retval = disable_snd_device(adev,
9951 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9952 list_remove(&uc_info.list);
9953 }
9954 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009955 return 0;
9956}
9957
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009958int update_patch(unsigned int num_sources,
9959 const struct audio_port_config *sources,
9960 unsigned int num_sinks,
9961 const struct audio_port_config *sinks,
9962 audio_patch_handle_t handle,
9963 struct audio_patch_info *p_info,
9964 patch_type_t patch_type, bool new_patch)
9965{
9966 ALOGD("%s: enter", __func__);
9967
9968 if (p_info == NULL) {
9969 ALOGE("%s: Invalid patch pointer", __func__);
9970 return -EINVAL;
9971 }
9972
9973 if (new_patch) {
9974 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9975 if (p_info->patch == NULL) {
9976 ALOGE("%s: Could not allocate patch", __func__);
9977 return -ENOMEM;
9978 }
9979 }
9980
9981 p_info->patch->id = handle;
9982 p_info->patch->num_sources = num_sources;
9983 p_info->patch->num_sinks = num_sinks;
9984
9985 for (int i = 0; i < num_sources; i++)
9986 p_info->patch->sources[i] = sources[i];
9987 for (int i = 0; i < num_sinks; i++)
9988 p_info->patch->sinks[i] = sinks[i];
9989
9990 p_info->patch_type = patch_type;
9991 return 0;
9992}
9993
9994audio_patch_handle_t generate_patch_handle()
9995{
9996 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9997 if (++patch_handle < 0)
9998 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9999 return patch_handle;
10000}
10001
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010002int adev_create_audio_patch(struct audio_hw_device *dev,
10003 unsigned int num_sources,
10004 const struct audio_port_config *sources,
10005 unsigned int num_sinks,
10006 const struct audio_port_config *sinks,
10007 audio_patch_handle_t *handle)
10008{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010009 int ret = 0;
10010 struct audio_device *adev = (struct audio_device *)dev;
10011 struct audio_patch_info *p_info = NULL;
10012 patch_type_t patch_type = PATCH_NONE;
10013 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10014 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10015 struct audio_stream_info *s_info = NULL;
10016 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010017 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010018 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10019 bool new_patch = false;
10020 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010021
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010022 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10023 num_sources, num_sinks, *handle);
10024
10025 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10026 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10027 ALOGE("%s: Invalid patch arguments", __func__);
10028 ret = -EINVAL;
10029 goto done;
10030 }
10031
10032 if (num_sources > 1) {
10033 ALOGE("%s: Multiple sources are not supported", __func__);
10034 ret = -EINVAL;
10035 goto done;
10036 }
10037
10038 if (sources == NULL || sinks == NULL) {
10039 ALOGE("%s: Invalid sources or sinks port config", __func__);
10040 ret = -EINVAL;
10041 goto done;
10042 }
10043
10044 ALOGV("%s: source role %d, source type %d", __func__,
10045 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010046 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010047
10048 // Populate source/sink information and fetch stream info
10049 switch (sources[0].type) {
10050 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10051 device_type = sources[0].ext.device.type;
10052 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010053 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010054 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10055 patch_type = PATCH_CAPTURE;
10056 io_handle = sinks[0].ext.mix.handle;
10057 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010058 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059 __func__, device_type, io_handle);
10060 } else {
10061 // Device to device patch is not implemented.
10062 // This space will need changes if audio HAL
10063 // handles device to device patches in the future.
10064 patch_type = PATCH_DEVICE_LOOPBACK;
10065 }
10066 break;
10067 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10068 io_handle = sources[0].ext.mix.handle;
10069 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010070 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010071 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010072 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010073 }
10074 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010075 ALOGD("%s: Playback patch from mix handle %d to device %x",
10076 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010077 break;
10078 case AUDIO_PORT_TYPE_SESSION:
10079 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010080 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10081 ret = -EINVAL;
10082 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 }
10084
10085 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010087 // Generate patch info and update patch
10088 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010089 *handle = generate_patch_handle();
10090 p_info = (struct audio_patch_info *)
10091 calloc(1, sizeof(struct audio_patch_info));
10092 if (p_info == NULL) {
10093 ALOGE("%s: Failed to allocate memory", __func__);
10094 pthread_mutex_unlock(&adev->lock);
10095 ret = -ENOMEM;
10096 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010098 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010099 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010100 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010101 if (p_info == NULL) {
10102 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10103 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010104 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 ret = -EINVAL;
10106 goto done;
10107 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010108 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010109 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010110 *handle, p_info, patch_type, new_patch);
10111
10112 // Fetch stream info of associated mix for playback or capture patches
10113 if (p_info->patch_type == PATCH_PLAYBACK ||
10114 p_info->patch_type == PATCH_CAPTURE) {
10115 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10116 if (s_info == NULL) {
10117 ALOGE("%s: Failed to obtain stream info", __func__);
10118 if (new_patch)
10119 free(p_info);
10120 pthread_mutex_unlock(&adev->lock);
10121 ret = -EINVAL;
10122 goto done;
10123 }
10124 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10125 s_info->patch_handle = *handle;
10126 stream = s_info->stream;
10127 }
10128 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129
10130 // Update routing for stream
10131 if (stream != NULL) {
10132 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010133 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010134 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010135 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010136 if (ret < 0) {
10137 pthread_mutex_lock(&adev->lock);
10138 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10139 if (new_patch)
10140 free(p_info);
10141 pthread_mutex_unlock(&adev->lock);
10142 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10143 goto done;
10144 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010145 }
10146
10147 // Add new patch to patch map
10148 if (!ret && new_patch) {
10149 pthread_mutex_lock(&adev->lock);
10150 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010151 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010152 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010153 }
10154
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010155done:
10156 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010157 num_sources,
10158 sources,
10159 num_sinks,
10160 sinks,
10161 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010162 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010163 num_sources,
10164 sources,
10165 num_sinks,
10166 sinks,
10167 handle);
10168 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010169}
10170
10171int adev_release_audio_patch(struct audio_hw_device *dev,
10172 audio_patch_handle_t handle)
10173{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010174 struct audio_device *adev = (struct audio_device *) dev;
10175 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010176 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010177 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010178
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010179 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10180 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10181 ret = -EINVAL;
10182 goto done;
10183 }
10184
10185 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010186 pthread_mutex_lock(&adev->lock);
10187 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010188 if (p_info == NULL) {
10189 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010190 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010191 ret = -EINVAL;
10192 goto done;
10193 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010194 struct audio_patch *patch = p_info->patch;
10195 if (patch == NULL) {
10196 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010197 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010198 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010199 goto done;
10200 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010201 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10202 switch (patch->sources[0].type) {
10203 case AUDIO_PORT_TYPE_MIX:
10204 io_handle = patch->sources[0].ext.mix.handle;
10205 break;
10206 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010207 if (p_info->patch_type == PATCH_CAPTURE)
10208 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010209 break;
10210 case AUDIO_PORT_TYPE_SESSION:
10211 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010212 pthread_mutex_unlock(&adev->lock);
10213 ret = -EINVAL;
10214 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010215 }
10216
10217 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010218 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010219 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010220 if (patch_type == PATCH_PLAYBACK ||
10221 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010222 struct audio_stream_info *s_info =
10223 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10224 if (s_info == NULL) {
10225 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10226 pthread_mutex_unlock(&adev->lock);
10227 goto done;
10228 }
10229 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10230 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010231 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010232 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010233
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010234 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010235 struct listnode devices;
10236 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010237 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010238 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010239 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010240 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010241 }
10242
10243 if (ret < 0)
10244 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10245
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010246done:
10247 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10248 audio_extn_auto_hal_release_audio_patch(dev, handle);
10249
10250 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010251 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010252}
10253
10254int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10255{
Derek Chenf13dd492018-11-13 14:53:51 -080010256 int ret = 0;
10257
10258 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10259 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10260 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010261}
10262
10263int adev_set_audio_port_config(struct audio_hw_device *dev,
10264 const struct audio_port_config *config)
10265{
Derek Chenf13dd492018-11-13 14:53:51 -080010266 int ret = 0;
10267
10268 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10269 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10270 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010271}
10272
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010273static int adev_dump(const audio_hw_device_t *device __unused,
10274 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010275{
10276 return 0;
10277}
10278
10279static int adev_close(hw_device_t *device)
10280{
Aalique Grahame22e49102018-12-18 14:23:57 -080010281 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010282 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010283
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010284 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010285 return 0;
10286
10287 pthread_mutex_lock(&adev_init_lock);
10288
10289 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010290 if (audio_extn_spkr_prot_is_enabled())
10291 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010292 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010293 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010294 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010295 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010296 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010297 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010298 audio_extn_utils_release_streams_cfg_lists(
10299 &adev->streams_output_cfg_list,
10300 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010301 if (audio_extn_qap_is_enabled())
10302 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010303 if (audio_extn_qaf_is_enabled())
10304 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010305 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010306 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010307 free(adev->snd_dev_ref_cnt);
10308 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010309 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10310 pcm_params_free(adev->use_case_table[i]);
10311 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010312 if (adev->adm_deinit)
10313 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010314 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010315 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010316 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010317 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010318 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010319 if (adev->device_cfg_params) {
10320 free(adev->device_cfg_params);
10321 adev->device_cfg_params = NULL;
10322 }
Derek Chend2530072014-11-24 12:39:14 -080010323 if(adev->ext_hw_plugin)
10324 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010325 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010326 free_map(adev->patch_map);
10327 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010328 free(device);
10329 adev = NULL;
10330 }
10331 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010332 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010333 return 0;
10334}
10335
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010336/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10337 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10338 * just that it _might_ work.
10339 */
10340static int period_size_is_plausible_for_low_latency(int period_size)
10341{
10342 switch (period_size) {
10343 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010344 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010345 case 240:
10346 case 320:
10347 case 480:
10348 return 1;
10349 default:
10350 return 0;
10351 }
10352}
10353
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010354static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10355{
10356 bool is_snd_card_status = false;
10357 bool is_ext_device_status = false;
10358 char value[32];
10359 int card = -1;
10360 card_status_t status;
10361
10362 if (cookie != adev || !parms)
10363 return;
10364
10365 if (!parse_snd_card_status(parms, &card, &status)) {
10366 is_snd_card_status = true;
10367 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10368 is_ext_device_status = true;
10369 } else {
10370 // not a valid event
10371 return;
10372 }
10373
10374 pthread_mutex_lock(&adev->lock);
10375 if (card == adev->snd_card || is_ext_device_status) {
10376 if (is_snd_card_status && adev->card_status != status) {
10377 adev->card_status = status;
10378 platform_snd_card_update(adev->platform, status);
10379 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010380 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010381 if (status == CARD_STATUS_OFFLINE)
10382 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010383 } else if (is_ext_device_status) {
10384 platform_set_parameters(adev->platform, parms);
10385 }
10386 }
10387 pthread_mutex_unlock(&adev->lock);
10388 return;
10389}
10390
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010391/* adev lock held */
10392int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010393{
10394 struct audio_usecase *uc_info;
Zhou Song3bbcee72020-12-27 19:13:04 +080010395 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010396 struct listnode devices;
Zhou Song3bbcee72020-12-27 19:13:04 +080010397 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010398
10399 uc_info = get_usecase_from_list(adev, out->usecase);
10400 if (uc_info == NULL) {
10401 ALOGE("%s: Could not find the usecase (%d) in the list",
10402 __func__, out->usecase);
10403 return -EINVAL;
10404 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010405 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010406
Zhou Song1f93fa52020-11-20 13:57:39 +080010407 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10408 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010409
10410 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010411 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010412 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010413 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010414 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010415 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10416 select_devices(adev, uc_info->id);
Zhou Song1f93fa52020-11-20 13:57:39 +080010417
10418 if (is_offload_usecase(out->usecase)) {
10419 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010420 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Song1f93fa52020-11-20 13:57:39 +080010421 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10422 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10423 } else {
10424 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010425 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010426 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010427 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010428 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010429 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010430 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +080010431 // mute stream and switch to speaker if suspended
10432 if (!out->a2dp_muted && !out->standby) {
Zhou Song1f93fa52020-11-20 13:57:39 +080010433 assign_devices(&devices, &out->device_list);
10434 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song3bbcee72020-12-27 19:13:04 +080010435 list_for_each(node, &adev->usecase_list) {
10436 usecase = node_to_item(node, struct audio_usecase, list);
10437 if ((usecase != uc_info) &&
10438 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10439 usecase->out_snd_device)) {
10440 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10441 break;
10442 }
10443 }
Zhou Song5e44b782021-01-14 16:48:03 +080010444 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP) {
10445 out->a2dp_muted = true;
10446 if (is_offload_usecase(out->usecase)) {
10447 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10448 compress_pause(out->compr);
10449 out_set_compr_volume(&out->stream, (float)0, (float)0);
10450 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10451 out_set_voip_volume(&out->stream, (float)0, (float)0);
10452 } else {
10453 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10454 /* wait for stale pcm drained before switching to speaker */
10455 uint32_t latency =
10456 (out->config.period_count * out->config.period_size * 1000) /
10457 (out->config.rate);
10458 usleep(latency * 1000);
10459 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010460 }
10461 select_devices(adev, out->usecase);
Zhou Song5e44b782021-01-14 16:48:03 +080010462 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10463 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Song1f93fa52020-11-20 13:57:39 +080010464 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010465 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10466 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010467 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010468 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010469 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010470 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010471 }
10472 ALOGV("%s: exit", __func__);
10473 return 0;
10474}
10475
Haynes Mathew George01156f92018-04-13 15:29:54 -070010476void adev_on_battery_status_changed(bool charging)
10477{
10478 pthread_mutex_lock(&adev->lock);
10479 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10480 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010481 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010482 pthread_mutex_unlock(&adev->lock);
10483}
10484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010485static int adev_open(const hw_module_t *module, const char *name,
10486 hw_device_t **device)
10487{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010488 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010489 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010490 char mixer_ctl_name[128] = {0};
10491 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010492
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010493 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010494 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10495
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010496 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010497 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010498 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010499 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010500 ALOGD("%s: returning existing instance of adev", __func__);
10501 ALOGD("%s: exit", __func__);
10502 pthread_mutex_unlock(&adev_init_lock);
10503 return 0;
10504 }
10505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010506 adev = calloc(1, sizeof(struct audio_device));
10507
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010508 if (!adev) {
10509 pthread_mutex_unlock(&adev_init_lock);
10510 return -ENOMEM;
10511 }
10512
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010513 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10514
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010515 // register audio ext hidl at the earliest
10516 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010517#ifdef DYNAMIC_LOG_ENABLED
10518 register_for_dynamic_logging("hal");
10519#endif
10520
Derek Chenf939fb72018-11-13 13:34:41 -080010521 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010522 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010523 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10524 maj_version = atoi(value);
10525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010526 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010527 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010528 adev->device.common.module = (struct hw_module_t *)module;
10529 adev->device.common.close = adev_close;
10530
10531 adev->device.init_check = adev_init_check;
10532 adev->device.set_voice_volume = adev_set_voice_volume;
10533 adev->device.set_master_volume = adev_set_master_volume;
10534 adev->device.get_master_volume = adev_get_master_volume;
10535 adev->device.set_master_mute = adev_set_master_mute;
10536 adev->device.get_master_mute = adev_get_master_mute;
10537 adev->device.set_mode = adev_set_mode;
10538 adev->device.set_mic_mute = adev_set_mic_mute;
10539 adev->device.get_mic_mute = adev_get_mic_mute;
10540 adev->device.set_parameters = adev_set_parameters;
10541 adev->device.get_parameters = adev_get_parameters;
10542 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10543 adev->device.open_output_stream = adev_open_output_stream;
10544 adev->device.close_output_stream = adev_close_output_stream;
10545 adev->device.open_input_stream = adev_open_input_stream;
10546 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010547 adev->device.create_audio_patch = adev_create_audio_patch;
10548 adev->device.release_audio_patch = adev_release_audio_patch;
10549 adev->device.get_audio_port = adev_get_audio_port;
10550 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010551 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010552 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010553
10554 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010555 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010556 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010557 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010558 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010559 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010560 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010561 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010562 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010563 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010564 /* Init audio and voice feature */
10565 audio_extn_feature_init();
10566 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010567 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010568 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010569 list_init(&adev->active_inputs_list);
10570 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010571 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010572 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10573 audio_extn_utils_hash_eq);
10574 if (!adev->io_streams_map) {
10575 ALOGE("%s: Could not create io streams map", __func__);
10576 ret = -ENOMEM;
10577 goto adev_open_err;
10578 }
10579 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10580 audio_extn_utils_hash_eq);
10581 if (!adev->patch_map) {
10582 ALOGE("%s: Could not create audio patch map", __func__);
10583 ret = -ENOMEM;
10584 goto adev_open_err;
10585 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010586 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010587 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010588 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010589 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010590 adev->perf_lock_opts[0] = 0x101;
10591 adev->perf_lock_opts[1] = 0x20E;
10592 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010593 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010594 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010595 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010596 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010597 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010598
Zhou Song68ebc352019-12-05 17:11:15 +080010599 audio_extn_perf_lock_init();
10600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010601 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010602 adev->platform = platform_init(adev);
10603 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010604 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010605 ret = -EINVAL;
10606 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010607 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010608
Aalique Grahame22e49102018-12-18 14:23:57 -080010609 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010610 if (audio_extn_qap_is_enabled()) {
10611 ret = audio_extn_qap_init(adev);
10612 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010613 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010614 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010615 }
10616 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10617 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10618 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010619
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010620 if (audio_extn_qaf_is_enabled()) {
10621 ret = audio_extn_qaf_init(adev);
10622 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010623 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010624 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010625 }
10626
10627 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10628 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10629 }
10630
Derek Chenae7b0342019-02-08 15:17:04 -080010631 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010632 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10633
Eric Laurentc4aef752013-09-12 17:45:53 -070010634 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10635 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10636 if (adev->visualizer_lib == NULL) {
10637 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10638 } else {
10639 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10640 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010641 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010642 "visualizer_hal_start_output");
10643 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010644 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010645 "visualizer_hal_stop_output");
10646 }
10647 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010648 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010649 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010650 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010651 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010652 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010653 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010654
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010655 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10656 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10657 if (adev->offload_effects_lib == NULL) {
10658 ALOGE("%s: DLOPEN failed for %s", __func__,
10659 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10660 } else {
10661 ALOGV("%s: DLOPEN successful for %s", __func__,
10662 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10663 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010664 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010665 "offload_effects_bundle_hal_start_output");
10666 adev->offload_effects_stop_output =
10667 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10668 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010669 adev->offload_effects_set_hpx_state =
10670 (int (*)(bool))dlsym(adev->offload_effects_lib,
10671 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010672 adev->offload_effects_get_parameters =
10673 (void (*)(struct str_parms *, struct str_parms *))
10674 dlsym(adev->offload_effects_lib,
10675 "offload_effects_bundle_get_parameters");
10676 adev->offload_effects_set_parameters =
10677 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10678 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010679 }
10680 }
10681
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010682 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10683 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10684 if (adev->adm_lib == NULL) {
10685 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10686 } else {
10687 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10688 adev->adm_init = (adm_init_t)
10689 dlsym(adev->adm_lib, "adm_init");
10690 adev->adm_deinit = (adm_deinit_t)
10691 dlsym(adev->adm_lib, "adm_deinit");
10692 adev->adm_register_input_stream = (adm_register_input_stream_t)
10693 dlsym(adev->adm_lib, "adm_register_input_stream");
10694 adev->adm_register_output_stream = (adm_register_output_stream_t)
10695 dlsym(adev->adm_lib, "adm_register_output_stream");
10696 adev->adm_deregister_stream = (adm_deregister_stream_t)
10697 dlsym(adev->adm_lib, "adm_deregister_stream");
10698 adev->adm_request_focus = (adm_request_focus_t)
10699 dlsym(adev->adm_lib, "adm_request_focus");
10700 adev->adm_abandon_focus = (adm_abandon_focus_t)
10701 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010702 adev->adm_set_config = (adm_set_config_t)
10703 dlsym(adev->adm_lib, "adm_set_config");
10704 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10705 dlsym(adev->adm_lib, "adm_request_focus_v2");
10706 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10707 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10708 adev->adm_on_routing_change = (adm_on_routing_change_t)
10709 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010710 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10711 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010712 }
10713 }
10714
Aalique Grahame22e49102018-12-18 14:23:57 -080010715 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010716 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010717 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010718 //initialize this to false for now,
10719 //this will be set to true through set param
10720 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010721
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010722 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010723 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010724
10725 if (k_enable_extended_precision)
10726 adev_verify_devices(adev);
10727
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010728 adev->dsp_bit_width_enforce_mode =
10729 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010730
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010731 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10732 &adev->streams_output_cfg_list,
10733 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010734
Kiran Kandi910e1862013-10-29 13:29:42 -070010735 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010736
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010737 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010738 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010739 trial = atoi(value);
10740 if (period_size_is_plausible_for_low_latency(trial)) {
10741 pcm_config_low_latency.period_size = trial;
10742 pcm_config_low_latency.start_threshold = trial / 4;
10743 pcm_config_low_latency.avail_min = trial / 4;
10744 configured_low_latency_capture_period_size = trial;
10745 }
10746 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010747 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10748 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010749 trial = atoi(value);
10750 if (period_size_is_plausible_for_low_latency(trial)) {
10751 configured_low_latency_capture_period_size = trial;
10752 }
10753 }
10754
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010755 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10756
Eric Laurent4b084132018-10-19 17:33:43 -070010757 adev->camera_orientation = CAMERA_DEFAULT;
10758
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010759 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010760 af_period_multiplier = atoi(value);
10761 if (af_period_multiplier < 0)
10762 af_period_multiplier = 2;
10763 else if (af_period_multiplier > 4)
10764 af_period_multiplier = 4;
10765
10766 ALOGV("new period_multiplier = %d", af_period_multiplier);
10767 }
10768
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010769 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010770
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010771 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010772 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010773 pthread_mutex_unlock(&adev_init_lock);
10774
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010775 if (adev->adm_init)
10776 adev->adm_data = adev->adm_init();
10777
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010778 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010779 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010780
10781 audio_extn_snd_mon_init();
10782 pthread_mutex_lock(&adev->lock);
10783 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10784 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010785 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10786 /*
10787 * if the battery state callback happens before charging can be queried,
10788 * it will be guarded with the adev->lock held in the cb function and so
10789 * the callback value will reflect the latest state
10790 */
10791 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010792 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010793 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010794 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010795 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010796 /* Allocate memory for Device config params */
10797 adev->device_cfg_params = (struct audio_device_config_param*)
10798 calloc(platform_get_max_codec_backend(),
10799 sizeof(struct audio_device_config_param));
10800 if (adev->device_cfg_params == NULL)
10801 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010802
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010803 /*
10804 * Check if new PSPD matrix mixer control is supported. If not
10805 * supported, then set flag so that old mixer ctrl is sent while
10806 * sending pspd coefficients on older kernel version. Query mixer
10807 * control for default pcm id and channel value one.
10808 */
10809 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10810 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10811
10812 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10813 if (!ctl) {
10814 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10815 __func__, mixer_ctl_name);
10816 adev->use_old_pspd_mix_ctrl = true;
10817 }
10818
Eric Laurent994a6932013-07-17 11:51:42 -070010819 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010820 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010821
10822adev_open_err:
10823 free_map(adev->patch_map);
10824 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010825 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010826 pthread_mutex_destroy(&adev->lock);
10827 free(adev);
10828 adev = NULL;
10829 *device = NULL;
10830 pthread_mutex_unlock(&adev_init_lock);
10831 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010832}
10833
10834static struct hw_module_methods_t hal_module_methods = {
10835 .open = adev_open,
10836};
10837
10838struct audio_module HAL_MODULE_INFO_SYM = {
10839 .common = {
10840 .tag = HARDWARE_MODULE_TAG,
10841 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10842 .hal_api_version = HARDWARE_HAL_API_VERSION,
10843 .id = AUDIO_HARDWARE_MODULE_ID,
10844 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010845 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010846 .methods = &hal_module_methods,
10847 },
10848};