blob: 334d4690fc1ee7dd4b3cf6f84c1b2beeb3b2765b [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) {
Ramjee Singha337a962021-12-14 14:13:41 +05301414
1415 struct audio_usecase *usecase;
1416 struct listnode *node;
1417 /* Disable SCO Devices and enable handset mic for active input stream */
1418 list_for_each(node, &adev->usecase_list) {
1419 usecase = node_to_item(node, struct audio_usecase, list);
1420 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
1421 is_sco_in_device_type(&usecase->stream.in->device_list)) {
1422 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
1423 reassign_device_list(&usecase->stream.in->device_list,
1424 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
1425 select_devices(adev, usecase->id);
1426 }
1427 }
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301428 if (audio_extn_a2dp_start_playback() < 0) {
1429 ALOGE(" fail to configure A2dp Source control path ");
1430 goto err;
1431 } else {
1432 adev->a2dp_started = true;
1433 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001434 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001435
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001436 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1437 (audio_extn_a2dp_start_capture() < 0)) {
1438 ALOGE(" fail to configure A2dp Sink control path ");
1439 goto err;
1440 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301441
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001442 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1443 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1444 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1445 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1446 ALOGE(" fail to configure sco control path ");
1447 goto err;
1448 }
Zhou Song12c29502019-03-16 10:37:18 +08001449 }
1450
Zhou Song331c8e52019-08-26 14:16:12 +08001451 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001452 /* due to the possibility of calibration overwrite between listen
1453 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001454 audio_extn_sound_trigger_update_device_status(snd_device,
1455 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301456 audio_extn_listen_update_device_status(snd_device,
1457 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001458 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001459 audio_extn_sound_trigger_update_device_status(snd_device,
1460 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301461 audio_extn_listen_update_device_status(snd_device,
1462 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001463 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001464 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001465 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001466 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301467
1468 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1469 !adev->native_playback_enabled &&
1470 audio_is_true_native_stream_active(adev)) {
1471 ALOGD("%s: %d: napb: enabling native mode in hardware",
1472 __func__, __LINE__);
1473 audio_route_apply_and_update_path(adev->audio_route,
1474 "true-native-mode");
1475 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301476 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301477 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1478 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001479 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001480 ALOGD("%s: init ec ref loopback", __func__);
1481 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1482 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001485err:
1486 adev->snd_dev_ref_cnt[snd_device]--;
1487 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488}
1489
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001490int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001491 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301493 int i, num_devices = 0;
1494 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001495 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1496
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001497 if (snd_device < SND_DEVICE_MIN ||
1498 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001499 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001500 return -EINVAL;
1501 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001502
1503 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1504 ALOGE("%s: Invalid sound device returned", __func__);
1505 return -EINVAL;
1506 }
1507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1509 ALOGE("%s: device ref cnt is already 0", __func__);
1510 return -EINVAL;
1511 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001512
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001514
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001515
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001517 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301518
Aalique Grahame22e49102018-12-18 14:23:57 -08001519 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1520
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001521 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1522 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001523 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001524
1525 // when speaker device is disabled, reset swap.
1526 // will be renabled on usecase start
1527 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001528 } else if (platform_split_snd_device(adev->platform,
1529 snd_device,
1530 &num_devices,
1531 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301532 for (i = 0; i < num_devices; i++) {
1533 disable_snd_device(adev, new_snd_devices[i]);
1534 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001535 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001536 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001537 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001538 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001539
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301540 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301541 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301542 adev->a2dp_started = false;
1543 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001544 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001545 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301547 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001548 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301549 adev->native_playback_enabled) {
1550 ALOGD("%s: %d: napb: disabling native mode in hardware",
1551 __func__, __LINE__);
1552 audio_route_reset_and_update_path(adev->audio_route,
1553 "true-native-mode");
1554 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001555 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301556 adev->asrc_mode_enabled) {
1557 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301558 disable_asrc_mode(adev);
1559 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001560 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301561 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001562 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001563 ALOGD("%s: deinit ec ref loopback", __func__);
1564 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1565 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001566
1567 audio_extn_utils_release_snd_device(snd_device);
1568 } else {
1569 if (platform_split_snd_device(adev->platform,
1570 snd_device,
1571 &num_devices,
1572 new_snd_devices) == 0) {
1573 for (i = 0; i < num_devices; i++) {
1574 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1575 }
1576 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 return 0;
1580}
1581
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001582/*
1583 legend:
1584 uc - existing usecase
1585 new_uc - new usecase
1586 d1, d11, d2 - SND_DEVICE enums
1587 a1, a2 - corresponding ANDROID device enums
1588 B1, B2 - backend strings
1589
1590case 1
1591 uc->dev d1 (a1) B1
1592 new_uc->dev d1 (a1), d2 (a2) B1, B2
1593
1594 resolution: disable and enable uc->dev on d1
1595
1596case 2
1597 uc->dev d1 (a1) B1
1598 new_uc->dev d11 (a1) B1
1599
1600 resolution: need to switch uc since d1 and d11 are related
1601 (e.g. speaker and voice-speaker)
1602 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1603
1604case 3
1605 uc->dev d1 (a1) B1
1606 new_uc->dev d2 (a2) B2
1607
1608 resolution: no need to switch uc
1609
1610case 4
1611 uc->dev d1 (a1) B1
1612 new_uc->dev d2 (a2) B1
1613
1614 resolution: disable enable uc-dev on d2 since backends match
1615 we cannot enable two streams on two different devices if they
1616 share the same backend. e.g. if offload is on speaker device using
1617 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1618 using the same backend, offload must also be switched to voice-handset.
1619
1620case 5
1621 uc->dev d1 (a1) B1
1622 new_uc->dev d1 (a1), d2 (a2) B1
1623
1624 resolution: disable enable uc-dev on d2 since backends match
1625 we cannot enable two streams on two different devices if they
1626 share the same backend.
1627
1628case 6
1629 uc->dev d1 (a1) B1
1630 new_uc->dev d2 (a1) B2
1631
1632 resolution: no need to switch
1633
1634case 7
1635 uc->dev d1 (a1), d2 (a2) B1, B2
1636 new_uc->dev d1 (a1) B1
1637
1638 resolution: no need to switch
1639
Zhou Song4ba65882018-07-09 14:48:07 +08001640case 8
1641 uc->dev d1 (a1) B1
1642 new_uc->dev d11 (a1), d2 (a2) B1, B2
1643 resolution: compared to case 1, for this case, d1 and d11 are related
1644 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301645
1646case 9
1647 uc->dev d1 (a1), d2(a2) B1 B2
1648 new_uc->dev d1 (a1), d22 (a2) B1, B2
1649 resolution: disable enable uc-dev on d2 since backends match
1650 we cannot enable two streams on two different devices if they
1651 share the same backend. This is special case for combo use case
1652 with a2dp and sco devices which uses same backend.
1653 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001654*/
1655static snd_device_t derive_playback_snd_device(void * platform,
1656 struct audio_usecase *uc,
1657 struct audio_usecase *new_uc,
1658 snd_device_t new_snd_device)
1659{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001660 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001661
1662 snd_device_t d1 = uc->out_snd_device;
1663 snd_device_t d2 = new_snd_device;
1664
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001665 list_init(&a1);
1666 list_init(&a2);
1667
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301668 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301669 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001670 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1671 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301672 break;
1673 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001674 assign_devices(&a1, &uc->stream.out->device_list);
1675 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301676 break;
1677 }
1678
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001679 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001680 if (!compare_devices(&a1, &a2) &&
1681 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001682 snd_device_t d3[2];
1683 int num_devices = 0;
1684 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001685 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001686 &num_devices,
1687 d3);
1688 if (ret < 0) {
1689 if (ret != -ENOSYS) {
1690 ALOGW("%s failed to split snd_device %d",
1691 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001692 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001693 }
1694 goto end;
1695 }
1696
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001697 if (platform_check_backends_match(d3[0], d3[1])) {
1698 return d2; // case 5
1699 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301700 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1701 platform_check_backends_match(d1, d2))
1702 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001703 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301704 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001705 // check if d1 is related to any of d3's
1706 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001707 return d1; // case 1
1708 else
1709 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001710 }
1711 } else {
1712 if (platform_check_backends_match(d1, d2)) {
1713 return d2; // case 2, 4
1714 } else {
1715 return d1; // case 6, 3
1716 }
1717 }
1718
1719end:
1720 return d2; // return whatever was calculated before.
1721}
1722
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001723static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301724 struct audio_usecase *uc_info,
1725 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001726{
1727 struct listnode *node;
1728 struct audio_usecase *usecase;
1729 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301730 snd_device_t uc_derive_snd_device;
1731 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001732 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1733 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001734 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301735 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001736 /*
1737 * This function is to make sure that all the usecases that are active on
1738 * the hardware codec backend are always routed to any one device that is
1739 * handled by the hardware codec.
1740 * For example, if low-latency and deep-buffer usecases are currently active
1741 * on speaker and out_set_parameters(headset) is received on low-latency
1742 * output, then we have to make sure deep-buffer is also switched to headset,
1743 * because of the limitation that both the devices cannot be enabled
1744 * at the same time as they share the same backend.
1745 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001746 /*
1747 * This call is to check if we need to force routing for a particular stream
1748 * If there is a backend configuration change for the device when a
1749 * new stream starts, then ADM needs to be closed and re-opened with the new
1750 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001751 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001752 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001753 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1754 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301755 /* For a2dp device reconfigure all active sessions
1756 * with new AFE encoder format based on a2dp state
1757 */
1758 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301759 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1760 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301761 audio_extn_a2dp_is_force_device_switch()) {
1762 force_routing = true;
1763 force_restart_session = true;
1764 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001765
1766 /*
1767 * Island cfg and power mode config needs to set before AFE port start.
1768 * Set force routing in case of voice device was enable before.
1769 */
1770 if (uc_info->type == VOICE_CALL &&
1771 voice_extn_is_voice_power_mode_supported() &&
1772 platform_check_and_update_island_power_status(adev->platform,
1773 uc_info,
1774 snd_device)) {
1775 force_routing = true;
1776 ALOGD("%s:becf: force routing %d for power mode supported device",
1777 __func__, force_routing);
1778 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301779 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1780
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001781 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001782 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001783 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001784 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1785 switch_device[i] = false;
1786
1787 list_for_each(node, &adev->usecase_list) {
1788 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001789
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301790 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1791 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301792 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301793 platform_get_snd_device_name(usecase->out_snd_device),
1794 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301795 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1796 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301797 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1798 usecase, uc_info, snd_device);
1799 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001800 (is_codec_backend_out_device_type(&usecase->device_list) ||
1801 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1802 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1803 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1804 is_a2dp_out_device_type(&usecase->device_list) ||
1805 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301806 ((force_restart_session) ||
1807 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301808 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1809 __func__, use_case_table[usecase->id],
1810 platform_get_snd_device_name(usecase->out_snd_device));
1811 disable_audio_route(adev, usecase);
1812 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301813 /* Enable existing usecase on derived playback device */
1814 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301815 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301816 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001817 }
1818 }
1819
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301820 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1821 num_uc_to_switch);
1822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001824 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301826 /* Make sure the previous devices to be disabled first and then enable the
1827 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 list_for_each(node, &adev->usecase_list) {
1829 usecase = node_to_item(node, struct audio_usecase, list);
1830 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001831 /* Check if output sound device to be switched can be split and if any
1832 of the split devices match with derived sound device */
1833 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1834 &num_devices, split_snd_devices) == 0) {
1835 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1836 for (i = 0; i < num_devices; i++) {
1837 /* Disable devices that do not match with derived sound device */
1838 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1839 disable_snd_device(adev, split_snd_devices[i]);
1840 }
1841 } else {
1842 disable_snd_device(adev, usecase->out_snd_device);
1843 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001844 }
1845 }
1846
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001847 list_for_each(node, &adev->usecase_list) {
1848 usecase = node_to_item(node, struct audio_usecase, list);
1849 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001850 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1851 &num_devices, split_snd_devices) == 0) {
1852 /* Enable derived sound device only if it does not match with
1853 one of the split sound devices. This is because the matching
1854 sound device was not disabled */
1855 bool should_enable = true;
1856 for (i = 0; i < num_devices; i++) {
1857 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1858 should_enable = false;
1859 break;
1860 }
1861 }
1862 if (should_enable)
1863 enable_snd_device(adev, derive_snd_device[usecase->id]);
1864 } else {
1865 enable_snd_device(adev, derive_snd_device[usecase->id]);
1866 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001867 }
1868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 /* Re-route all the usecases on the shared backend other than the
1871 specified usecase to new snd devices */
1872 list_for_each(node, &adev->usecase_list) {
1873 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301874 /* Update the out_snd_device only before enabling the audio route */
1875 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301876 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301877 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1878 use_case_table[usecase->id],
1879 platform_get_snd_device_name(usecase->out_snd_device));
1880 /* Update voc calibration before enabling Voice/VoIP route */
1881 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1882 status = platform_switch_voice_call_device_post(adev->platform,
1883 usecase->out_snd_device,
1884 platform_get_input_snd_device(
1885 adev->platform, NULL,
1886 &uc_info->device_list,
1887 usecase->type));
1888 enable_audio_route(adev, usecase);
1889 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1890 out_set_voip_volume(&usecase->stream.out->stream,
1891 usecase->stream.out->volume_l,
1892 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 }
1895 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001896 }
1897}
1898
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301899static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001900 struct audio_usecase *uc_info,
1901 snd_device_t snd_device)
1902{
1903 struct listnode *node;
1904 struct audio_usecase *usecase;
1905 bool switch_device[AUDIO_USECASE_MAX];
1906 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001907 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001908 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001909
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301910 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1911 snd_device);
1912 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301913
1914 /*
1915 * Make sure out devices is checked against out codec backend device and
1916 * also in devices against in codec backend. Checking out device against in
1917 * codec backend or vice versa causes issues.
1918 */
1919 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001920 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001921
1922 /*
1923 * Island cfg and power mode config needs to set before AFE port start.
1924 * Set force routing in case of voice device was enable before.
1925 */
1926
1927 if (uc_info->type == VOICE_CALL &&
1928 voice_extn_is_voice_power_mode_supported() &&
1929 platform_check_and_update_island_power_status(adev->platform,
1930 uc_info,
1931 snd_device)) {
1932 force_routing = true;
1933 ALOGD("%s:becf: force routing %d for power mode supported device",
1934 __func__, force_routing);
1935 }
1936
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001937 /*
1938 * This function is to make sure that all the active capture usecases
1939 * are always routed to the same input sound device.
1940 * For example, if audio-record and voice-call usecases are currently
1941 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1942 * is received for voice call then we have to make sure that audio-record
1943 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1944 * because of the limitation that two devices cannot be enabled
1945 * at the same time if they share the same backend.
1946 */
1947 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1948 switch_device[i] = false;
1949
1950 list_for_each(node, &adev->usecase_list) {
1951 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301952 /*
1953 * TODO: Enhance below condition to handle BT sco/USB multi recording
1954 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301955
1956 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1957 (usecase->in_snd_device != snd_device || force_routing));
1958 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1959 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1960 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001961 ((backend_check_cond &&
1962 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001963 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001964 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001965 is_single_device_type_equal(&usecase->device_list,
1966 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Anver sadhique3ece6422022-01-21 12:26:28 +05301967 platform_check_all_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001968 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001969 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301970 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001971 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001972 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001973 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001974 switch_device[usecase->id] = true;
1975 num_uc_to_switch++;
1976 }
1977 }
1978
1979 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001980 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001981
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301982 /* Make sure the previous devices to be disabled first and then enable the
1983 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001984 list_for_each(node, &adev->usecase_list) {
1985 usecase = node_to_item(node, struct audio_usecase, list);
1986 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001987 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001988 }
1989 }
1990
1991 list_for_each(node, &adev->usecase_list) {
1992 usecase = node_to_item(node, struct audio_usecase, list);
1993 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001994 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001995 }
1996 }
1997
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001998 /* Re-route all the usecases on the shared backend other than the
1999 specified usecase to new snd devices */
2000 list_for_each(node, &adev->usecase_list) {
2001 usecase = node_to_item(node, struct audio_usecase, list);
2002 /* Update the in_snd_device only before enabling the audio route */
2003 if (switch_device[usecase->id] ) {
2004 usecase->in_snd_device = snd_device;
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302005 /* Update voc calibration before enabling Voice/VoIP route */
2006 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
2007 snd_device_t voip_snd_device;
2008 voip_snd_device = platform_get_output_snd_device(adev->platform,
2009 usecase->stream.out,
2010 usecase->type);
2011 status = platform_switch_voice_call_device_post(adev->platform,
2012 voip_snd_device,
2013 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002014 }
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302015 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002016 }
2017 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002018 }
2019}
2020
Mingming Yin3a941d42016-02-17 18:08:05 -08002021static void reset_hdmi_sink_caps(struct stream_out *out) {
2022 int i = 0;
2023
2024 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2025 out->supported_channel_masks[i] = 0;
2026 }
2027 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2028 out->supported_formats[i] = 0;
2029 }
2030 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2031 out->supported_sample_rates[i] = 0;
2032 }
2033}
2034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002036static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037{
Mingming Yin3a941d42016-02-17 18:08:05 -08002038 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002039 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2040 out->extconn.cs.controller,
2041 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042
Mingming Yin3a941d42016-02-17 18:08:05 -08002043 reset_hdmi_sink_caps(out);
2044
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002045 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002046 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002047 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002048 out->extconn.cs.stream);
2049 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002050 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002051 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002052 }
2053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002056 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002057 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002058 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2059 case 6:
2060 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2061 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2062 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2063 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2064 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2065 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 break;
2067 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002068 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002069 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070 break;
2071 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002072
2073 // check channel format caps
2074 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002075 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2076 out->extconn.cs.controller,
2077 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002078 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2079 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2080 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2081 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2082 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2083 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2084 }
2085
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002086 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2087 out->extconn.cs.controller,
2088 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002089 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2090 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2091 }
2092
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002093 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2094 out->extconn.cs.controller,
2095 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002096 ALOGV(":%s HDMI supports DTS format", __func__);
2097 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2098 }
2099
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002100 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2101 out->extconn.cs.controller,
2102 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002103 ALOGV(":%s HDMI supports DTS HD format", __func__);
2104 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2105 }
2106
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002107 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2108 out->extconn.cs.controller,
2109 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002110 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2111 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2112 }
2113
Mingming Yin3a941d42016-02-17 18:08:05 -08002114
2115 // check sample rate caps
2116 i = 0;
2117 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002118 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2119 out->extconn.cs.controller,
2120 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002121 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2122 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2123 }
2124 }
2125
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002126 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127}
2128
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002129static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2130 uint32_t *supported_sample_rates __unused,
2131 uint32_t max_rates __unused)
2132{
2133 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2134 supported_sample_rates,
2135 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302136 ssize_t i = 0;
2137
2138 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002139 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2140 supported_sample_rates[i]);
2141 }
2142 return count;
2143}
2144
2145static inline int read_usb_sup_channel_masks(bool is_playback,
2146 audio_channel_mask_t *supported_channel_masks,
2147 uint32_t max_masks)
2148{
2149 int channels = audio_extn_usb_get_max_channels(is_playback);
2150 int channel_count;
2151 uint32_t num_masks = 0;
2152 if (channels > MAX_HIFI_CHANNEL_COUNT)
2153 channels = MAX_HIFI_CHANNEL_COUNT;
2154
2155 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002156 // start from 2 channels as framework currently doesn't support mono.
2157 if (channels >= FCC_2) {
2158 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2159 }
2160 for (channel_count = FCC_2;
2161 channel_count <= channels && num_masks < max_masks;
2162 ++channel_count) {
2163 supported_channel_masks[num_masks++] =
2164 audio_channel_mask_for_index_assignment_from_count(channel_count);
2165 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002166 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002167 // For capture we report all supported channel masks from 1 channel up.
2168 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002169 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2170 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002171 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2172 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2173 if (channel_count <= FCC_2) {
2174 mask = audio_channel_in_mask_from_count(channel_count);
2175 supported_channel_masks[num_masks++] = mask;
2176 }
2177 const audio_channel_mask_t index_mask =
2178 audio_channel_mask_for_index_assignment_from_count(channel_count);
2179 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2180 supported_channel_masks[num_masks++] = index_mask;
2181 }
2182 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002183 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302184
vincenttewf51c94e2019-05-07 10:28:53 +08002185 for (size_t i = 0; i < num_masks; ++i) {
2186 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2187 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302188 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002189 return num_masks;
2190}
2191
2192static inline int read_usb_sup_formats(bool is_playback __unused,
2193 audio_format_t *supported_formats,
2194 uint32_t max_formats __unused)
2195{
2196 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2197 switch (bitwidth) {
2198 case 24:
2199 // XXX : usb.c returns 24 for s24 and s24_le?
2200 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2201 break;
2202 case 32:
2203 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2204 break;
2205 case 16:
2206 default :
2207 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2208 break;
2209 }
2210 ALOGV("%s: %s supported format %d", __func__,
2211 is_playback ? "P" : "C", bitwidth);
2212 return 1;
2213}
2214
2215static inline int read_usb_sup_params_and_compare(bool is_playback,
2216 audio_format_t *format,
2217 audio_format_t *supported_formats,
2218 uint32_t max_formats,
2219 audio_channel_mask_t *mask,
2220 audio_channel_mask_t *supported_channel_masks,
2221 uint32_t max_masks,
2222 uint32_t *rate,
2223 uint32_t *supported_sample_rates,
2224 uint32_t max_rates) {
2225 int ret = 0;
2226 int num_formats;
2227 int num_masks;
2228 int num_rates;
2229 int i;
2230
2231 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2232 max_formats);
2233 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2234 max_masks);
2235
2236 num_rates = read_usb_sup_sample_rates(is_playback,
2237 supported_sample_rates, max_rates);
2238
2239#define LUT(table, len, what, dflt) \
2240 for (i=0; i<len && (table[i] != what); i++); \
2241 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2242
2243 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2244 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2245 LUT(supported_sample_rates, num_rates, *rate, 0);
2246
2247#undef LUT
2248 return ret < 0 ? -EINVAL : 0; // HACK TBD
2249}
2250
Alexy Josephb1379942016-01-29 15:49:38 -08002251audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002252 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002253{
2254 struct audio_usecase *usecase;
2255 struct listnode *node;
2256
2257 list_for_each(node, &adev->usecase_list) {
2258 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002259 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002260 ALOGV("%s: usecase id %d", __func__, usecase->id);
2261 return usecase->id;
2262 }
2263 }
2264 return USECASE_INVALID;
2265}
2266
Alexy Josephb1379942016-01-29 15:49:38 -08002267struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002268 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002269{
2270 struct audio_usecase *usecase;
2271 struct listnode *node;
2272
2273 list_for_each(node, &adev->usecase_list) {
2274 usecase = node_to_item(node, struct audio_usecase, list);
2275 if (usecase->id == uc_id)
2276 return usecase;
2277 }
2278 return NULL;
2279}
2280
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302281/*
2282 * is a true native playback active
2283 */
2284bool audio_is_true_native_stream_active(struct audio_device *adev)
2285{
2286 bool active = false;
2287 int i = 0;
2288 struct listnode *node;
2289
2290 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2291 ALOGV("%s:napb: not in true mode or non hdphones device",
2292 __func__);
2293 active = false;
2294 goto exit;
2295 }
2296
2297 list_for_each(node, &adev->usecase_list) {
2298 struct audio_usecase *uc;
2299 uc = node_to_item(node, struct audio_usecase, list);
2300 struct stream_out *curr_out =
2301 (struct stream_out*) uc->stream.out;
2302
2303 if (curr_out && PCM_PLAYBACK == uc->type) {
2304 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2305 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2306 uc->id, curr_out->sample_rate,
2307 curr_out->bit_width,
2308 platform_get_snd_device_name(uc->out_snd_device));
2309
2310 if (is_offload_usecase(uc->id) &&
2311 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2312 active = true;
2313 ALOGD("%s:napb:native stream detected", __func__);
2314 }
2315 }
2316 }
2317exit:
2318 return active;
2319}
2320
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002321uint32_t adev_get_dsp_bit_width_enforce_mode()
2322{
2323 if (adev == NULL) {
2324 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2325 return 0;
2326 }
2327 return adev->dsp_bit_width_enforce_mode;
2328}
2329
2330static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2331{
2332 char value[PROPERTY_VALUE_MAX];
2333 int trial;
2334 uint32_t dsp_bit_width_enforce_mode = 0;
2335
2336 if (!mixer) {
2337 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2338 __func__);
2339 return 0;
2340 }
2341
2342 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2343 value, NULL) > 0) {
2344 trial = atoi(value);
2345 switch (trial) {
2346 case 16:
2347 dsp_bit_width_enforce_mode = 16;
2348 break;
2349 case 24:
2350 dsp_bit_width_enforce_mode = 24;
2351 break;
2352 case 32:
2353 dsp_bit_width_enforce_mode = 32;
2354 break;
2355 default:
2356 dsp_bit_width_enforce_mode = 0;
2357 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2358 break;
2359 }
2360 }
2361
2362 return dsp_bit_width_enforce_mode;
2363}
2364
2365static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2366 uint32_t enforce_mode,
2367 bool enable)
2368{
2369 struct mixer_ctl *ctl = NULL;
2370 const char *mixer_ctl_name = "ASM Bit Width";
2371 uint32_t asm_bit_width_mode = 0;
2372
2373 if (enforce_mode == 0) {
2374 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2375 return;
2376 }
2377
2378 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2379 if (!ctl) {
2380 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2381 __func__, mixer_ctl_name);
2382 return;
2383 }
2384
2385 if (enable)
2386 asm_bit_width_mode = enforce_mode;
2387 else
2388 asm_bit_width_mode = 0;
2389
2390 ALOGV("%s DSP bit width feature status is %d width=%d",
2391 __func__, enable, asm_bit_width_mode);
2392 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2393 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2394 asm_bit_width_mode);
2395
2396 return;
2397}
2398
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302399/*
2400 * if native DSD playback active
2401 */
2402bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2403{
2404 bool active = false;
2405 struct listnode *node = NULL;
2406 struct audio_usecase *uc = NULL;
2407 struct stream_out *curr_out = NULL;
2408
2409 list_for_each(node, &adev->usecase_list) {
2410 uc = node_to_item(node, struct audio_usecase, list);
2411 curr_out = (struct stream_out*) uc->stream.out;
2412
2413 if (curr_out && PCM_PLAYBACK == uc->type &&
2414 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2415 active = true;
2416 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302417 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302418 }
2419 }
2420 return active;
2421}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302422
2423static bool force_device_switch(struct audio_usecase *usecase)
2424{
2425 bool ret = false;
2426 bool is_it_true_mode = false;
2427
Zhou Song30f2c3e2018-02-08 14:02:15 +08002428 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302429 usecase->type == TRANSCODE_LOOPBACK_RX ||
2430 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002431 return false;
2432 }
2433
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002434 if(usecase->stream.out == NULL) {
2435 ALOGE("%s: stream.out is NULL", __func__);
2436 return false;
2437 }
2438
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302439 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002440 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002441 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2442 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302443 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2444 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2445 (!is_it_true_mode && adev->native_playback_enabled)){
2446 ret = true;
2447 ALOGD("napb: time to toggle native mode");
2448 }
2449 }
2450
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302451 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302452 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2453 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002454 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302455 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302456 ALOGD("Force a2dp device switch to update new encoder config");
2457 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002458 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302459
Florian Pfister1a84f312018-07-19 14:38:18 +02002460 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302461 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2462 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002463 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302464 return ret;
2465}
2466
Aalique Grahame22e49102018-12-18 14:23:57 -08002467static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2468{
2469 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2470}
2471
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302472bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2473{
2474 bool ret=false;
2475 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002476 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2477 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302478 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2479 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002480 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302481 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002482 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2483 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302484 ret = true;
2485
2486 return ret;
2487}
2488
2489bool is_a2dp_device(snd_device_t out_snd_device)
2490{
2491 bool ret=false;
2492 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2493 ret = true;
2494
2495 return ret;
2496}
2497
2498bool is_bt_soc_on(struct audio_device *adev)
2499{
2500 struct mixer_ctl *ctl;
2501 char *mixer_ctl_name = "BT SOC status";
2502 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2503 bool bt_soc_status = true;
2504 if (!ctl) {
2505 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2506 __func__, mixer_ctl_name);
2507 /*This is to ensure we dont break targets which dont have the kernel change*/
2508 return true;
2509 }
2510 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2511 ALOGD("BT SOC status: %d",bt_soc_status);
2512 return bt_soc_status;
2513}
2514
Zhou Song331c8e52019-08-26 14:16:12 +08002515static int configure_btsco_sample_rate(snd_device_t snd_device)
2516{
2517 struct mixer_ctl *ctl = NULL;
2518 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2519 char *rate_str = NULL;
2520 bool is_rx_dev = true;
2521
2522 if (is_btsco_device(snd_device, snd_device)) {
2523 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2524 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2525 if (!ctl_sr_tx || !ctl_sr_rx) {
2526 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2527 if (!ctl_sr)
2528 return -ENOSYS;
2529 }
2530
2531 switch (snd_device) {
2532 case SND_DEVICE_OUT_BT_SCO:
2533 rate_str = "KHZ_8";
2534 break;
2535 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2536 case SND_DEVICE_IN_BT_SCO_MIC:
2537 rate_str = "KHZ_8";
2538 is_rx_dev = false;
2539 break;
2540 case SND_DEVICE_OUT_BT_SCO_WB:
2541 rate_str = "KHZ_16";
2542 break;
2543 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2544 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2545 rate_str = "KHZ_16";
2546 is_rx_dev = false;
2547 break;
2548 default:
2549 return 0;
2550 }
2551
2552 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2553 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2554 return -ENOSYS;
2555 }
2556 return 0;
2557}
2558
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302559int out_standby_l(struct audio_stream *stream);
2560
Eric Laurent637e2d42018-11-15 12:24:31 -08002561struct stream_in *adev_get_active_input(const struct audio_device *adev)
2562{
2563 struct listnode *node;
2564 struct stream_in *last_active_in = NULL;
2565
2566 /* Get last added active input.
2567 * TODO: We may use a priority mechanism to pick highest priority active source */
2568 list_for_each(node, &adev->usecase_list)
2569 {
2570 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2571 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2572 last_active_in = usecase->stream.in;
2573 }
2574
2575 return last_active_in;
2576}
2577
2578struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2579{
2580 struct listnode *node;
2581
2582 /* First check active inputs with voice communication source and then
2583 * any input if audio mode is in communication */
2584 list_for_each(node, &adev->usecase_list)
2585 {
2586 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2587 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2588 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2589 return usecase->stream.in;
2590 }
2591 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2592 return adev_get_active_input(adev);
2593
2594 return NULL;
2595}
2596
Carter Hsu2e429db2019-05-14 18:50:52 +08002597/*
2598 * Aligned with policy.h
2599 */
2600static inline int source_priority(int inputSource)
2601{
2602 switch (inputSource) {
2603 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2604 return 9;
2605 case AUDIO_SOURCE_CAMCORDER:
2606 return 8;
2607 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2608 return 7;
2609 case AUDIO_SOURCE_UNPROCESSED:
2610 return 6;
2611 case AUDIO_SOURCE_MIC:
2612 return 5;
2613 case AUDIO_SOURCE_ECHO_REFERENCE:
2614 return 4;
2615 case AUDIO_SOURCE_FM_TUNER:
2616 return 3;
2617 case AUDIO_SOURCE_VOICE_RECOGNITION:
2618 return 2;
2619 case AUDIO_SOURCE_HOTWORD:
2620 return 1;
2621 default:
2622 break;
2623 }
2624 return 0;
2625}
2626
2627static struct stream_in *get_priority_input(struct audio_device *adev)
2628{
2629 struct listnode *node;
2630 struct audio_usecase *usecase;
2631 int last_priority = 0, priority;
2632 struct stream_in *priority_in = NULL;
2633 struct stream_in *in;
2634
2635 list_for_each(node, &adev->usecase_list) {
2636 usecase = node_to_item(node, struct audio_usecase, list);
2637 if (usecase->type == PCM_CAPTURE) {
2638 in = usecase->stream.in;
2639 if (!in)
2640 continue;
2641 priority = source_priority(in->source);
2642
2643 if (priority > last_priority) {
2644 last_priority = priority;
2645 priority_in = in;
2646 }
2647 }
2648 }
2649 return priority_in;
2650}
2651
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002652int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002654 snd_device_t out_snd_device = SND_DEVICE_NONE;
2655 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002656 struct audio_usecase *usecase = NULL;
2657 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002658 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002659 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302660 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002661 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302664 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2665
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002666 usecase = get_usecase_from_list(adev, uc_id);
2667 if (usecase == NULL) {
2668 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2669 return -EINVAL;
2670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002672 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002673 (usecase->type == VOIP_CALL) ||
2674 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302675 if(usecase->stream.out == NULL) {
2676 ALOGE("%s: stream.out is NULL", __func__);
2677 return -EINVAL;
2678 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002679 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002680 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2681 uc_id);
2682 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2683 uc_id);
2684 } else {
2685 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302686 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002687 in_snd_device = platform_get_input_snd_device(adev->platform,
2688 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302689 &usecase->stream.out->device_list,
2690 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002691 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002692 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302693 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302694 if (usecase->stream.inout == NULL) {
2695 ALOGE("%s: stream.inout is NULL", __func__);
2696 return -EINVAL;
2697 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002698 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302699 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2700 stream_out.format = usecase->stream.inout->out_config.format;
2701 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302702 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002703 assign_devices(&usecase->device_list,
2704 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302705 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2706 if (usecase->stream.inout == NULL) {
2707 ALOGE("%s: stream.inout is NULL", __func__);
2708 return -EINVAL;
2709 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302710 struct listnode out_devices;
2711 list_init(&out_devices);
2712 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2713 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002714 assign_devices(&usecase->device_list,
2715 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002716 } else {
2717 /*
2718 * If the voice call is active, use the sound devices of voice call usecase
2719 * so that it would not result any device switch. All the usecases will
2720 * be switched to new device when select_devices() is called for voice call
2721 * usecase. This is to avoid switching devices for voice call when
2722 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002723 * choose voice call device only if the use case device is
2724 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002725 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002726 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002727 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002728 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002729 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2730 is_codec_backend_out_device_type(&usecase->device_list)) ||
2731 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2732 is_codec_backend_in_device_type(&usecase->device_list)) ||
2733 is_single_device_type_equal(&vc_usecase->device_list,
2734 AUDIO_DEVICE_OUT_HEARING_AID) ||
2735 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002736 AUDIO_DEVICE_IN_VOICE_CALL) ||
2737 (is_single_device_type_equal(&usecase->device_list,
2738 AUDIO_DEVICE_IN_USB_HEADSET) &&
2739 is_single_device_type_equal(&vc_usecase->device_list,
Kamalakar Yalasirid2323462021-01-28 14:52:38 +05302740 AUDIO_DEVICE_OUT_USB_HEADSET))||
2741 (is_single_device_type_equal(&usecase->device_list,
2742 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) &&
2743 is_codec_backend_out_device_type(&vc_usecase->device_list)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002744 in_snd_device = vc_usecase->in_snd_device;
2745 out_snd_device = vc_usecase->out_snd_device;
2746 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002747 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002748 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002749 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002750 if ((voip_usecase != NULL) &&
2751 (usecase->type == PCM_PLAYBACK) &&
2752 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002753 out_snd_device_backend_match = platform_check_backends_match(
2754 voip_usecase->out_snd_device,
2755 platform_get_output_snd_device(
2756 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302757 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002758 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2760 (is_codec_backend_out_device_type(&usecase->device_list) ||
2761 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002762 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002763 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002764 in_snd_device = voip_usecase->in_snd_device;
2765 out_snd_device = voip_usecase->out_snd_device;
2766 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002767 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002768 hfp_ucid = audio_extn_hfp_get_usecase();
2769 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002770 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002771 in_snd_device = hfp_usecase->in_snd_device;
2772 out_snd_device = hfp_usecase->out_snd_device;
2773 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002774 }
2775 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302776 if (usecase->stream.out == NULL) {
2777 ALOGE("%s: stream.out is NULL", __func__);
2778 return -EINVAL;
2779 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002780 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002781 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002782 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002783 struct stream_out *voip_out = adev->primary_output;
2784 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002785 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002786 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2787 else
2788 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302789 usecase->stream.out,
2790 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002791 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002792
Eric Laurent637e2d42018-11-15 12:24:31 -08002793 if (voip_usecase)
2794 voip_out = voip_usecase->stream.out;
2795
2796 if (usecase->stream.out == voip_out && voip_in != NULL)
2797 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002798 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002799 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302800 if (usecase->stream.in == NULL) {
2801 ALOGE("%s: stream.in is NULL", __func__);
2802 return -EINVAL;
2803 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002804 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002805 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002806 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002808 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002809 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002810
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002811 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002812 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002813 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2814 USECASE_AUDIO_PLAYBACK_VOIP);
2815
Carter Hsu2e429db2019-05-14 18:50:52 +08002816 usecase->stream.in->enable_ec_port = false;
2817
Zhou Song62ea0282020-03-22 19:53:01 +08002818 bool is_ha_usecase = adev->ha_proxy_enable ?
2819 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2820 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2821 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002822 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002823 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002824 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002825 } else if (adev->primary_output &&
2826 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002827 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002828 } else {
2829 /* forcing speaker o/p device to get matching i/p pair
2830 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002831 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002832 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002833 priority_in = voip_in;
2834 } else {
2835 /* get the input with the highest priority source*/
2836 priority_in = get_priority_input(adev);
2837
2838 if (!priority_in)
2839 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002840 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002841
Eric Laurent637e2d42018-11-15 12:24:31 -08002842 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002843 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302844 &out_devices,
2845 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002847 }
2848 }
2849
2850 if (out_snd_device == usecase->out_snd_device &&
2851 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302852
2853 if (!force_device_switch(usecase))
2854 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 }
2856
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002857 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002858 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002859 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002860 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2861 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302862 }
2863
Aalique Grahame22e49102018-12-18 14:23:57 -08002864 if (out_snd_device != SND_DEVICE_NONE &&
2865 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2866 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2867 __func__,
2868 use_case_table[uc_id],
2869 adev->last_logged_snd_device[uc_id][0],
2870 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2871 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2872 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2873 -1,
2874 out_snd_device,
2875 platform_get_snd_device_name(out_snd_device),
2876 platform_get_snd_device_acdb_id(out_snd_device));
2877 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2878 }
2879 if (in_snd_device != SND_DEVICE_NONE &&
2880 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2881 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2882 __func__,
2883 use_case_table[uc_id],
2884 adev->last_logged_snd_device[uc_id][1],
2885 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2886 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2887 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2888 -1,
2889 in_snd_device,
2890 platform_get_snd_device_name(in_snd_device),
2891 platform_get_snd_device_acdb_id(in_snd_device));
2892 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2893 }
2894
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 /*
2897 * Limitation: While in call, to do a device switch we need to disable
2898 * and enable both RX and TX devices though one of them is same as current
2899 * device.
2900 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002901 if ((usecase->type == VOICE_CALL) &&
2902 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2903 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002904 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002905 }
2906
2907 if (((usecase->type == VOICE_CALL) ||
2908 (usecase->type == VOIP_CALL)) &&
2909 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2910 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302911 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002912 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002913 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002914
2915 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302916 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002917 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002918 }
2919
Aalique Grahame22e49102018-12-18 14:23:57 -08002920 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2921 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002922 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302923 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002924 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2925 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2926 else
2927 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302928 }
2929
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002930 /* Disable current sound devices */
2931 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002932 disable_audio_route(adev, usecase);
2933 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 }
2935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002937 disable_audio_route(adev, usecase);
2938 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 }
2940
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002941 /* Applicable only on the targets that has external modem.
2942 * New device information should be sent to modem before enabling
2943 * the devices to reduce in-call device switch time.
2944 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002945 if ((usecase->type == VOICE_CALL) &&
2946 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2947 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002948 status = platform_switch_voice_call_enable_device_config(adev->platform,
2949 out_snd_device,
2950 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002951 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002953 /* Enable new sound devices */
2954 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002955 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302956 if (platform_check_codec_asrc_support(adev->platform))
2957 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002958 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 }
2960
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002961 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302962 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002963 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002964 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002965
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302966 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07002967 status = platform_switch_voice_call_device_post(adev->platform,
2968 out_snd_device,
2969 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002970
sangwoo170731f2013-06-08 15:36:36 +09002971 usecase->in_snd_device = in_snd_device;
2972 usecase->out_snd_device = out_snd_device;
2973
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302974 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2975 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302976 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002977 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002978 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002979 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2980 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2981 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2982 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2983 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2984 /*
2985 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2986 * configured device sample rate, if not update the COPP rate to be equal to the
2987 * device sample rate, else open COPP at stream sample rate
2988 */
2989 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2990 usecase->stream.out->sample_rate,
2991 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302992 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302993 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2994 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302995 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002996 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2997 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2998 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2999 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08003000 }
3001 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08003002
Shalini Manjunatha8ae54892020-12-29 13:02:25 +05303003 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
3004 struct stream_in *voip_in = get_voice_communication_input(adev);
3005 struct audio_usecase *voip_in_usecase = NULL;
3006 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
3007 if (voip_in != NULL &&
3008 voip_in_usecase != NULL &&
3009 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
3010 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
3011 (voip_in_usecase->in_snd_device ==
3012 platform_get_input_snd_device(adev->platform, voip_in,
3013 &usecase->stream.out->device_list,usecase->type))) {
3014 /*
3015 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
3016 * for enabling echo-reference-voip with correct port
3017 */
3018 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3019 disable_audio_route(adev, voip_in_usecase);
3020 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3021 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3022 enable_audio_route(adev, voip_in_usecase);
3023 }
3024 }
3025
3026
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003027 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003028
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003029 /* If input stream is already running then effect needs to be
3030 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003031 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003032 check_and_enable_effect(adev);
3033
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003034 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003035 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303036 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003037 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3038
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003039 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303040 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003041 voice_extn_compress_voip_is_started(adev))
3042 voice_set_sidetone(adev, out_snd_device, true);
3043 }
3044
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003045 /* Applicable only on the targets that has external modem.
3046 * Enable device command should be sent to modem only after
3047 * enabling voice call mixer controls
3048 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003049 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003050 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3051 out_snd_device,
3052 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303053
3054 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003055 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303056 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003057 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303058 if (is_bt_soc_on(adev) == false){
3059 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003060 if (in->pcm != NULL)
3061 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303062 }
3063 }
3064 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3065 && usecase->stream.out->started) {
3066 if (is_bt_soc_on(adev) == false) {
3067 ALOGD("BT SCO/A2DP disconnected while in connection");
3068 out_standby_l(&usecase->stream.out->stream.common);
3069 }
3070 }
3071 } else if ((usecase->stream.out != NULL) &&
3072 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303073 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3074 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003075 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303076 usecase->stream.out->started) {
3077 if (is_bt_soc_on(adev) == false) {
3078 ALOGD("BT SCO/A2dp disconnected while in connection");
3079 out_standby_l(&usecase->stream.out->stream.common);
3080 }
3081 }
3082 }
3083
Yung Ti Su70cb8242018-06-22 17:38:47 +08003084 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003085 struct stream_out *voip_out = voip_usecase->stream.out;
3086 audio_extn_utils_send_app_type_gain(adev,
3087 voip_out->app_type_cfg.app_type,
3088 &voip_out->app_type_cfg.gain[0]);
3089 }
3090
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303091 ALOGD("%s: done",__func__);
3092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 return status;
3094}
3095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096static int stop_input_stream(struct stream_in *in)
3097{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303098 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303100
3101 if (in == NULL) {
3102 ALOGE("%s: stream_in ptr is NULL", __func__);
3103 return -EINVAL;
3104 }
3105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003107 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108
Eric Laurent994a6932013-07-17 11:51:42 -07003109 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003110 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 uc_info = get_usecase_from_list(adev, in->usecase);
3112 if (uc_info == NULL) {
3113 ALOGE("%s: Could not find the usecase (%d) in the list",
3114 __func__, in->usecase);
3115 return -EINVAL;
3116 }
3117
Carter Hsu2e429db2019-05-14 18:50:52 +08003118 priority_in = get_priority_input(adev);
3119
Derek Chenea197282019-01-07 17:35:01 -08003120 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3121 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003122
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003123 /* Close in-call recording streams */
3124 voice_check_and_stop_incall_rec_usecase(adev, in);
3125
Eric Laurent150dbfe2013-02-27 14:31:02 -08003126 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003127 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003128
3129 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003130 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003132 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303133 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3134
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003135 list_remove(&uc_info->list);
3136 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Carter Hsu2e429db2019-05-14 18:50:52 +08003138 if (priority_in == in) {
3139 priority_in = get_priority_input(adev);
3140 if (priority_in)
3141 select_devices(adev, priority_in->usecase);
3142 }
3143
Vatsal Buchac09ae062018-11-14 13:25:08 +05303144 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003145 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 return ret;
3147}
3148
3149int start_input_stream(struct stream_in *in)
3150{
3151 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003152 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303154
3155 if (in == NULL) {
3156 ALOGE("%s: stream_in ptr is NULL", __func__);
3157 return -EINVAL;
3158 }
3159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003161 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003162 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163
Mingming Yin2664a5b2015-09-03 10:53:11 -07003164 if (get_usecase_from_list(adev, usecase) == NULL)
3165 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303166 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3167 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003168
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303169 if (CARD_STATUS_OFFLINE == in->card_status||
3170 CARD_STATUS_OFFLINE == adev->card_status) {
3171 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303172 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303173 goto error_config;
3174 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303175
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003176 if (is_sco_in_device_type(&in->device_list)) {
Lakshman Chaluvaraju88bb65c2021-02-02 15:50:11 +05303177 if (!adev->bt_sco_on || audio_extn_a2dp_source_is_ready()) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303178 ALOGE("%s: SCO profile is not ready, return error", __func__);
3179 ret = -EIO;
3180 goto error_config;
3181 }
3182 }
3183
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003184 /* Check if source matches incall recording usecase criteria */
3185 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3186 if (ret)
3187 goto error_config;
3188 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003189 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3190
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303191 if (audio_extn_cin_attached_usecase(in))
3192 audio_extn_cin_acquire_usecase(in);
3193
Mingming Yin2664a5b2015-09-03 10:53:11 -07003194 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3195 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3196 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003197 ret = -EINVAL;
3198 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003199 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003200
Eric Laurentb23d5282013-05-14 15:27:20 -07003201 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 if (in->pcm_device_id < 0) {
3203 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3204 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003205 ret = -EINVAL;
3206 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003210
3211 if (!uc_info) {
3212 ret = -ENOMEM;
3213 goto error_config;
3214 }
3215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 uc_info->id = in->usecase;
3217 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003218 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003219 list_init(&uc_info->device_list);
3220 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003221 uc_info->in_snd_device = SND_DEVICE_NONE;
3222 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003224 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003225 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303226 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3227 adev->perf_lock_opts,
3228 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003229 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230
Derek Chenea197282019-01-07 17:35:01 -08003231 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3232 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003233
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303234 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3235
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303236 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303237 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303238 if (ret)
3239 goto error_open;
3240 else
3241 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003242 }
3243
Haynes Mathew George16081042017-05-31 17:16:49 -07003244 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003245 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003246 ALOGE("%s: pcm stream not ready", __func__);
3247 goto error_open;
3248 }
3249 ret = pcm_start(in->pcm);
3250 if (ret < 0) {
3251 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3252 goto error_open;
3253 }
3254 } else {
3255 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3256 unsigned int pcm_open_retry_count = 0;
3257
Zhou Song62ea0282020-03-22 19:53:01 +08003258 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3259 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003260 flags |= PCM_MMAP | PCM_NOIRQ;
3261 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3262 } else if (in->realtime) {
3263 flags |= PCM_MMAP | PCM_NOIRQ;
3264 }
3265
Garmond Leunge2433c32017-09-28 21:51:22 -07003266 if (audio_extn_ffv_get_stream() == in) {
3267 ALOGD("%s: ffv stream, update pcm config", __func__);
3268 audio_extn_ffv_update_pcm_config(&config);
3269 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003270 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3271 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3272
3273 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003274 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003275 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003276 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003277 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303278 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303279 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3280 adev->card_status = CARD_STATUS_OFFLINE;
3281 in->card_status = CARD_STATUS_OFFLINE;
3282 ret = -EIO;
3283 goto error_open;
3284 }
3285
Haynes Mathew George16081042017-05-31 17:16:49 -07003286 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3287 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3288 if (in->pcm != NULL) {
3289 pcm_close(in->pcm);
3290 in->pcm = NULL;
3291 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003292 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003293 ret = -EIO;
3294 goto error_open;
3295 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003296 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003297 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3298 continue;
3299 }
3300 break;
3301 }
3302
3303 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003304 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003305 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003306 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003307 if (ret < 0) {
3308 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3309 pcm_close(in->pcm);
3310 in->pcm = NULL;
3311 goto error_open;
3312 }
3313 register_in_stream(in);
3314 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003315 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003316 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003317 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003318 if (ret < 0) {
3319 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320 pcm_close(in->pcm);
3321 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003322 goto error_open;
3323 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003324 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003325 }
3326
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003327 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003328 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3329 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003330
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003331 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303332 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3333
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303334done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003335 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303336 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003337 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303338 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003339 return ret;
3340
3341error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003342 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303343 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003345
Eric Laurentc8400632013-02-14 19:04:54 -08003346error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003347 if (audio_extn_cin_attached_usecase(in))
3348 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303349 /*
3350 * sleep 50ms to allow sufficient time for kernel
3351 * drivers to recover incases like SSR.
3352 */
3353 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003354 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303355 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003356 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357}
3358
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003359void lock_input_stream(struct stream_in *in)
3360{
3361 pthread_mutex_lock(&in->pre_lock);
3362 pthread_mutex_lock(&in->lock);
3363 pthread_mutex_unlock(&in->pre_lock);
3364}
3365
3366void lock_output_stream(struct stream_out *out)
3367{
3368 pthread_mutex_lock(&out->pre_lock);
3369 pthread_mutex_lock(&out->lock);
3370 pthread_mutex_unlock(&out->pre_lock);
3371}
3372
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373/* must be called with out->lock locked */
3374static int send_offload_cmd_l(struct stream_out* out, int command)
3375{
3376 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3377
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003378 if (!cmd) {
3379 ALOGE("failed to allocate mem for command 0x%x", command);
3380 return -ENOMEM;
3381 }
3382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383 ALOGVV("%s %d", __func__, command);
3384
3385 cmd->cmd = command;
3386 list_add_tail(&out->offload_cmd_list, &cmd->node);
3387 pthread_cond_signal(&out->offload_cond);
3388 return 0;
3389}
3390
Gautam Manamfeeb1162020-12-24 14:08:04 +05303391/* must be called with out->lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003392static void stop_compressed_output_l(struct stream_out *out)
3393{
Gautam Manamfeeb1162020-12-24 14:08:04 +05303394 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 out->offload_state = OFFLOAD_STATE_IDLE;
Gautam Manamfeeb1162020-12-24 14:08:04 +05303396 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003398 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003399 if (out->compr != NULL) {
3400 compress_stop(out->compr);
3401 while (out->offload_thread_blocked) {
3402 pthread_cond_wait(&out->cond, &out->lock);
3403 }
3404 }
3405}
3406
Varun Balaraje49253e2017-07-06 19:48:56 +05303407bool is_interactive_usecase(audio_usecase_t uc_id)
3408{
3409 unsigned int i;
3410 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3411 if (uc_id == interactive_usecases[i])
3412 return true;
3413 }
3414 return false;
3415}
3416
3417static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3418{
3419 audio_usecase_t ret_uc = USECASE_INVALID;
3420 unsigned int intract_uc_index;
3421 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3422
3423 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3424 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3425 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3426 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3427 ret_uc = interactive_usecases[intract_uc_index];
3428 break;
3429 }
3430 }
3431
3432 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3433 return ret_uc;
3434}
3435
3436static void free_interactive_usecase(struct audio_device *adev,
3437 audio_usecase_t uc_id)
3438{
3439 unsigned int interact_uc_index;
3440 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3441
3442 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3443 if (interactive_usecases[interact_uc_index] == uc_id) {
3444 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3445 break;
3446 }
3447 }
3448 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3449}
3450
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003451bool is_offload_usecase(audio_usecase_t uc_id)
3452{
3453 unsigned int i;
3454 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3455 if (uc_id == offload_usecases[i])
3456 return true;
3457 }
3458 return false;
3459}
3460
Dhananjay Kumarac341582017-02-23 23:42:25 +05303461static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003462{
vivek mehta446c3962015-09-14 10:57:35 -07003463 audio_usecase_t ret_uc = USECASE_INVALID;
3464 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003465 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003466 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303467 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003468 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3469 else
3470 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003471
vivek mehta446c3962015-09-14 10:57:35 -07003472 pthread_mutex_lock(&adev->lock);
3473 if (get_usecase_from_list(adev, ret_uc) != NULL)
3474 ret_uc = USECASE_INVALID;
3475 pthread_mutex_unlock(&adev->lock);
3476
3477 return ret_uc;
3478 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003479
3480 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003481 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3482 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3483 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3484 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003485 break;
3486 }
3487 }
vivek mehta446c3962015-09-14 10:57:35 -07003488
3489 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3490 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003491}
3492
3493static void free_offload_usecase(struct audio_device *adev,
3494 audio_usecase_t uc_id)
3495{
vivek mehta446c3962015-09-14 10:57:35 -07003496 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003497 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003498
3499 if (!adev->multi_offload_enable)
3500 return;
3501
3502 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3503 if (offload_usecases[offload_uc_index] == uc_id) {
3504 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003505 break;
3506 }
3507 }
3508 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3509}
3510
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511static void *offload_thread_loop(void *context)
3512{
3513 struct stream_out *out = (struct stream_out *) context;
3514 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003515 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003518 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3520
3521 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003522 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003523 out->offload_state = OFFLOAD_STATE_IDLE;
3524 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 for (;;) {
3526 struct offload_cmd *cmd = NULL;
3527 stream_callback_event_t event;
3528 bool send_callback = false;
3529
3530 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3531 __func__, list_empty(&out->offload_cmd_list),
3532 out->offload_state);
3533 if (list_empty(&out->offload_cmd_list)) {
3534 ALOGV("%s SLEEPING", __func__);
3535 pthread_cond_wait(&out->offload_cond, &out->lock);
3536 ALOGV("%s RUNNING", __func__);
3537 continue;
3538 }
3539
3540 item = list_head(&out->offload_cmd_list);
3541 cmd = node_to_item(item, struct offload_cmd, node);
3542 list_remove(item);
3543
3544 ALOGVV("%s STATE %d CMD %d out->compr %p",
3545 __func__, out->offload_state, cmd->cmd, out->compr);
3546
3547 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3548 free(cmd);
3549 break;
3550 }
3551
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003552 // allow OFFLOAD_CMD_ERROR reporting during standby
3553 // this is needed to handle failures during compress_open
3554 // Note however that on a pause timeout, the stream is closed
3555 // and no offload usecase will be active. Therefore this
3556 // special case is needed for compress_open failures alone
3557 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3558 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003559 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003560 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003561 pthread_cond_signal(&out->cond);
3562 continue;
3563 }
3564 out->offload_thread_blocked = true;
3565 pthread_mutex_unlock(&out->lock);
3566 send_callback = false;
3567 switch(cmd->cmd) {
3568 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003569 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003571 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003572 send_callback = true;
3573 event = STREAM_CBK_EVENT_WRITE_READY;
3574 break;
3575 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003576 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303577 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003578 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303579 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003580 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303581 if (ret < 0)
3582 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303583 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303584 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003585 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003586 else
3587 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003588 if (-ENETRESET != ret && !(-EINTR == ret &&
3589 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303590 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303591 pthread_mutex_lock(&out->lock);
3592 out->send_new_metadata = 1;
3593 out->send_next_track_params = true;
3594 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303595 event = STREAM_CBK_EVENT_DRAIN_READY;
3596 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3597 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303598 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003599 break;
3600 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003601 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003602 ret = compress_drain(out->compr);
3603 ALOGD("copl(%p):out of compress_drain", out);
3604 // EINTR check avoids drain interruption due to SSR
3605 if (-ENETRESET != ret && !(-EINTR == ret &&
3606 CARD_STATUS_OFFLINE == out->card_status)) {
3607 send_callback = true;
3608 event = STREAM_CBK_EVENT_DRAIN_READY;
3609 } else
3610 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303612 case OFFLOAD_CMD_ERROR:
3613 ALOGD("copl(%p): sending error callback to AF", out);
3614 send_callback = true;
3615 event = STREAM_CBK_EVENT_ERROR;
3616 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003617 default:
3618 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3619 break;
3620 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003621 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003622 out->offload_thread_blocked = false;
3623 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003624 if (send_callback && out->client_callback) {
3625 ALOGVV("%s: sending client_callback event %d", __func__, event);
3626 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003627 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003628 free(cmd);
3629 }
3630
3631 pthread_cond_signal(&out->cond);
3632 while (!list_empty(&out->offload_cmd_list)) {
3633 item = list_head(&out->offload_cmd_list);
3634 list_remove(item);
3635 free(node_to_item(item, struct offload_cmd, node));
3636 }
3637 pthread_mutex_unlock(&out->lock);
3638
3639 return NULL;
3640}
3641
3642static int create_offload_callback_thread(struct stream_out *out)
3643{
3644 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3645 list_init(&out->offload_cmd_list);
3646 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3647 offload_thread_loop, out);
3648 return 0;
3649}
3650
3651static int destroy_offload_callback_thread(struct stream_out *out)
3652{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003653 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 stop_compressed_output_l(out);
3655 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3656
3657 pthread_mutex_unlock(&out->lock);
3658 pthread_join(out->offload_thread, (void **) NULL);
3659 pthread_cond_destroy(&out->offload_cond);
3660
3661 return 0;
3662}
3663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664static int stop_output_stream(struct stream_out *out)
3665{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303666 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 struct audio_usecase *uc_info;
3668 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003669 bool has_voip_usecase =
3670 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
Eric Laurent994a6932013-07-17 11:51:42 -07003672 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003673 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 uc_info = get_usecase_from_list(adev, out->usecase);
3675 if (uc_info == NULL) {
3676 ALOGE("%s: Could not find the usecase (%d) in the list",
3677 __func__, out->usecase);
3678 return -EINVAL;
3679 }
3680
Zhou Song1f93fa52020-11-20 13:57:39 +08003681 out->a2dp_muted = false;
3682
Derek Chenea197282019-01-07 17:35:01 -08003683 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3684 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003685
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003686 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303687 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003688 if (adev->visualizer_stop_output != NULL)
3689 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003690
3691 audio_extn_dts_remove_state_notifier_node(out->usecase);
3692
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003693 if (adev->offload_effects_stop_output != NULL)
3694 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003695 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3696 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3697 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003698 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003699
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003700 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3701 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003702 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003703 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003704
Eric Laurent150dbfe2013-02-27 14:31:02 -08003705 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003706 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003707
3708 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003709 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710
Aalique Grahame22e49102018-12-18 14:23:57 -08003711 audio_extn_extspk_update(adev->extspk);
3712
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003713 if (is_offload_usecase(out->usecase)) {
3714 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3715 adev->dsp_bit_width_enforce_mode,
3716 false);
3717 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003718 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003719 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3720 false);
3721
3722 if (ret != 0)
3723 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3724 /* default service interval was successfully updated,
3725 reopen USB backend with new service interval */
3726 ret = 0;
3727 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003728
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003729 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303730 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003731 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303732 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003733 ALOGV("Disable passthrough , reset mixer to pcm");
3734 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003735#ifdef AUDIO_GKI_ENABLED
3736 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3737 out->compr_config.codec->reserved[0] = 0;
3738#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003739 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003740#endif
Mingming Yin21854652016-04-13 11:54:02 -07003741 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003742 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3743 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003744
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303745 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003746 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303747 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303748
Manish Dewangan21a850a2017-08-14 12:03:55 +05303749 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003750 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3751 if (ret < 0)
3752 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3753 }
3754
juyuchen2d415992018-11-16 14:15:16 +08003755 /* 1) media + voip output routing to handset must route media back to
3756 speaker when voip stops.
3757 2) trigger voip input to reroute when voip output changes to
3758 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003759 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003760 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003761 struct listnode *node;
3762 struct audio_usecase *usecase;
3763 list_for_each(node, &adev->usecase_list) {
3764 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003765 if ((usecase->type == PCM_CAPTURE &&
3766 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3767 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003768 continue;
3769
3770 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3771 __func__, usecase->id, use_case_table[usecase->id],
3772 out->usecase, use_case_table[out->usecase]);
3773 select_devices(adev, usecase->id);
3774 }
3775 }
3776
Garmond Leung5fd0b552018-04-17 11:56:12 -07003777 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003778 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 return ret;
3780}
3781
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003782struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3783 unsigned int flags, unsigned int pcm_open_retry_count,
3784 struct pcm_config *config)
3785{
3786 struct pcm* pcm = NULL;
3787
3788 while (1) {
3789 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3790 if (pcm == NULL || !pcm_is_ready(pcm)) {
3791 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3792 if (pcm != NULL) {
3793 pcm_close(pcm);
3794 pcm = NULL;
3795 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003796 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003797 return NULL;
3798
Weiyin Jiang72197252019-10-09 11:49:32 +08003799 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003800 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3801 continue;
3802 }
3803 break;
3804 }
3805
3806 if (pcm_is_ready(pcm)) {
3807 int ret = pcm_prepare(pcm);
3808 if (ret < 0) {
3809 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3810 pcm_close(pcm);
3811 pcm = NULL;
3812 }
3813 }
3814
3815 return pcm;
3816}
3817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818int start_output_stream(struct stream_out *out)
3819{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 struct audio_usecase *uc_info;
3822 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003823 char mixer_ctl_name[128];
3824 struct mixer_ctl *ctl = NULL;
3825 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303826 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003827 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828
Haynes Mathew George380745d2017-10-04 15:27:45 -07003829 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003830 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3831 ret = -EINVAL;
3832 goto error_config;
3833 }
3834
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003835 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303836 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003837 get_device_types(&out->device_list), is_haptic_usecase);
3838
3839 bool is_speaker_active = compare_device_type(&out->device_list,
3840 AUDIO_DEVICE_OUT_SPEAKER);
3841 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3842 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303843
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303844 if (CARD_STATUS_OFFLINE == out->card_status ||
3845 CARD_STATUS_OFFLINE == adev->card_status) {
3846 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303847 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003848 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303849 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303850
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003851 //Update incall music usecase to reflect correct voice session
3852 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3853 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3854 if (ret != 0) {
3855 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3856 __func__, ret);
3857 goto error_config;
3858 }
3859 }
3860
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003861 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003862 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003863 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303864 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303865 } else {
Zhou Song9ebf6792020-09-23 22:49:01 +08003866 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303867 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3868 ret = -EAGAIN;
3869 goto error_config;
3870 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303871 }
3872 }
3873 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003874 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303875 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003876 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303877 //combo usecase just by pass a2dp
3878 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003879 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303880 } else {
3881 ALOGE("%s: SCO profile is not ready, return error", __func__);
3882 ret = -EAGAIN;
3883 goto error_config;
3884 }
3885 }
3886 }
3887
Eric Laurentb23d5282013-05-14 15:27:20 -07003888 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 if (out->pcm_device_id < 0) {
3890 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3891 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003892 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003893 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 }
3895
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003896 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003897 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3898 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003899 if (adev->haptic_pcm_device_id < 0) {
3900 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3901 __func__, adev->haptic_pcm_device_id, out->usecase);
3902 ret = -EINVAL;
3903 goto error_config;
3904 }
3905 }
3906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003908
3909 if (!uc_info) {
3910 ret = -ENOMEM;
3911 goto error_config;
3912 }
3913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 uc_info->id = out->usecase;
3915 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003916 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003917 list_init(&uc_info->device_list);
3918 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003919 uc_info->in_snd_device = SND_DEVICE_NONE;
3920 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003921
3922 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003923 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003924 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3925 /* USB backend is not reopened immediately.
3926 This is eventually done as part of select_devices */
3927 }
3928
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003929 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930
Wei Wangf7ca6c92017-11-21 14:51:20 -08003931 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303932 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3933 adev->perf_lock_opts,
3934 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303935
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003936 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303937 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303938 if (audio_extn_passthru_is_enabled() &&
3939 audio_extn_passthru_is_passthrough_stream(out)) {
3940 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303941 }
3942 }
3943
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003944 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003945 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303946 if (!a2dp_combo) {
3947 check_a2dp_restore_l(adev, out, false);
3948 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003949 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, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003955 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003956 reassign_device_list(&out->device_list,
3957 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303958 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003959 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303960 }
3961 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303962 select_devices(adev, out->usecase);
3963 if (is_a2dp_out_device_type(&out->device_list) &&
3964 !adev->a2dp_started) {
3965 if (is_speaker_active || is_speaker_safe_active) {
3966 struct listnode dev;
3967 list_init(&dev);
3968 assign_devices(&dev, &out->device_list);
3969 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3970 reassign_device_list(&out->device_list,
3971 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3972 else
3973 reassign_device_list(&out->device_list,
3974 AUDIO_DEVICE_OUT_SPEAKER, "");
3975 select_devices(adev, out->usecase);
3976 assign_devices(&out->device_list, &dev);
3977 } else {
3978 ret = -EINVAL;
3979 goto error_open;
3980 }
3981 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303982 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003983
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003984 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3985 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003986 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003987 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003988
Derek Chenea197282019-01-07 17:35:01 -08003989 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3990 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003991
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003992 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3993 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003994
3995 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003996 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003997 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3998 ALOGE("%s: pcm stream not ready", __func__);
3999 goto error_open;
4000 }
4001 ret = pcm_start(out->pcm);
4002 if (ret < 0) {
4003 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
4004 goto error_open;
4005 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07004006 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07004007 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004008 unsigned int flags = PCM_OUT;
4009 unsigned int pcm_open_retry_count = 0;
4010 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
4011 flags |= PCM_MMAP | PCM_NOIRQ;
4012 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004013 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08004014 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004015 } else
4016 flags |= PCM_MONOTONIC;
4017
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004018 if ((adev->vr_audio_mode_enabled) &&
4019 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4020 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4021 "PCM_Dev %d Topology", out->pcm_device_id);
4022 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4023 if (!ctl) {
4024 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4025 __func__, mixer_ctl_name);
4026 } else {
4027 //if success use ULLPP
4028 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4029 __func__, mixer_ctl_name, out->pcm_device_id);
4030 //There is a still a possibility that some sessions
4031 // that request for FAST|RAW when 3D audio is active
4032 //can go through ULLPP. Ideally we expects apps to
4033 //listen to audio focus and stop concurrent playback
4034 //Also, we will look for mode flag (voice_in_communication)
4035 //before enabling the realtime flag.
4036 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4037 }
4038 }
4039
Surendar Karka91fa3682018-07-02 18:12:12 +05304040 if (out->realtime)
4041 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4042 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4043
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004044 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4045 flags, pcm_open_retry_count,
4046 &(out->config));
4047 if (out->pcm == NULL) {
4048 ret = -EIO;
4049 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004051
4052 if (is_haptic_usecase) {
4053 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4054 adev->haptic_pcm_device_id,
4055 flags, pcm_open_retry_count,
4056 &(adev->haptics_config));
4057 // failure to open haptics pcm shouldnt stop audio,
4058 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004059
4060 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4061 ALOGD("%s: enable haptic audio synchronization", __func__);
4062 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4063 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004064 }
4065
Surendar Karka91fa3682018-07-02 18:12:12 +05304066 if (!out->realtime)
4067 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304068 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004069
Zhou Song2b8f28f2017-09-11 10:51:38 +08004070 // apply volume for voip playback after path is set up
4071 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4072 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304073 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4074 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304075 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4076 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004077 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4078 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304079 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004080 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004081 /*
4082 * set custom channel map if:
4083 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4084 * 2. custom channel map has been set by client
4085 * else default channel map of FC/FR/FL can always be set to DSP
4086 */
4087 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4088 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4089 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004090 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4091 adev->dsp_bit_width_enforce_mode,
4092 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004094 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004095 out->compr = compress_open(adev->snd_card,
4096 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004097 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004098 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304099 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304100 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4101 adev->card_status = CARD_STATUS_OFFLINE;
4102 out->card_status = CARD_STATUS_OFFLINE;
4103 ret = -EIO;
4104 goto error_open;
4105 }
4106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004107 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004108 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004109 compress_close(out->compr);
4110 out->compr = NULL;
4111 ret = -EIO;
4112 goto error_open;
4113 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304114 /* compress_open sends params of the track, so reset the flag here */
4115 out->is_compr_metadata_avail = false;
4116
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004117 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004118 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004119
Fred Oh3f43e742015-03-04 18:42:34 -08004120 /* Since small bufs uses blocking writes, a write will be blocked
4121 for the default max poll time (20s) in the event of an SSR.
4122 Reduce the poll time to observe and deal with SSR faster.
4123 */
Ashish Jain5106d362016-05-11 19:23:33 +05304124 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004125 compress_set_max_poll_wait(out->compr, 1000);
4126 }
4127
Manish Dewangan69426c82017-01-30 17:35:36 +05304128 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304129 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304130
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004131 audio_extn_dts_create_state_notifier_node(out->usecase);
4132 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4133 popcount(out->channel_mask),
4134 out->playback_started);
4135
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004136#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304137 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004138 audio_extn_dolby_send_ddp_endp_params(adev);
4139#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304140 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4141 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004142 if (adev->visualizer_start_output != NULL)
4143 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4144 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304145 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004146 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004147 }
Derek Chenf13dd492018-11-13 14:53:51 -08004148
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004149 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004150 /* Update cached volume from media to offload/direct stream */
4151 struct listnode *node = NULL;
4152 list_for_each(node, &adev->active_outputs_list) {
4153 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4154 streams_output_ctxt_t,
4155 list);
4156 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4157 out->volume_l = out_ctxt->output->volume_l;
4158 out->volume_r = out_ctxt->output->volume_r;
4159 }
4160 }
4161 out_set_compr_volume(&out->stream,
4162 out->volume_l, out->volume_r);
4163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004165
4166 if (ret == 0) {
4167 register_out_stream(out);
4168 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004169 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4170 ALOGE("%s: pcm stream not ready", __func__);
4171 goto error_open;
4172 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004173 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004174 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004175 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004176 if (ret < 0)
4177 goto error_open;
4178 }
4179 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004180 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304181 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004182 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004183
vivek mehtad15d2bf2019-05-17 13:35:10 -07004184 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4185 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4186 audio_low_latency_hint_start();
4187 }
4188
Manish Dewangan21a850a2017-08-14 12:03:55 +05304189 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004190 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004191 if (ret < 0)
4192 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4193 }
4194
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004195 // consider a scenario where on pause lower layers are tear down.
4196 // so on resume, swap mixer control need to be sent only when
4197 // backend is active, hence rather than sending from enable device
4198 // sending it from start of streamtream
4199
4200 platform_set_swap_channels(adev, true);
4201
Haynes Mathew George380745d2017-10-04 15:27:45 -07004202 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304203 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004204 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004205error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004206 if (adev->haptic_pcm) {
4207 pcm_close(adev->haptic_pcm);
4208 adev->haptic_pcm = NULL;
4209 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004210 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304211 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004213error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304214 /*
4215 * sleep 50ms to allow sufficient time for kernel
4216 * drivers to recover incases like SSR.
4217 */
4218 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004219error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004220 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304221 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004222 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223}
4224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225static int check_input_parameters(uint32_t sample_rate,
4226 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004227 int channel_count,
4228 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004230 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304232 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4233 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4234 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004235 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004236 !audio_extn_compr_cap_format_supported(format) &&
4237 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004238 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004239
Aalique Grahame22e49102018-12-18 14:23:57 -08004240 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4241 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4242 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4243 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4244 return -EINVAL;
4245 }
4246
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004247 switch (channel_count) {
4248 case 1:
4249 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304250 case 3:
4251 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004252 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004253 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304254 case 10:
4255 case 12:
4256 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004257 break;
4258 default:
4259 ret = -EINVAL;
4260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261
4262 switch (sample_rate) {
4263 case 8000:
4264 case 11025:
4265 case 12000:
4266 case 16000:
4267 case 22050:
4268 case 24000:
4269 case 32000:
4270 case 44100:
4271 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004272 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304273 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004274 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304275 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276 break;
4277 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004278 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 }
4280
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004281 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282}
4283
Naresh Tanniru04f71882018-06-26 17:46:22 +05304284
4285/** Add a value in a list if not already present.
4286 * @return true if value was successfully inserted or already present,
4287 * false if the list is full and does not contain the value.
4288 */
4289static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4290 for (size_t i = 0; i < list_length; i++) {
4291 if (list[i] == value) return true; // value is already present
4292 if (list[i] == 0) { // no values in this slot
4293 list[i] = value;
4294 return true; // value inserted
4295 }
4296 }
4297 return false; // could not insert value
4298}
4299
4300/** Add channel_mask in supported_channel_masks if not already present.
4301 * @return true if channel_mask was successfully inserted or already present,
4302 * false if supported_channel_masks is full and does not contain channel_mask.
4303 */
4304static void register_channel_mask(audio_channel_mask_t channel_mask,
4305 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4306 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4307 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4308}
4309
4310/** Add format in supported_formats if not already present.
4311 * @return true if format was successfully inserted or already present,
4312 * false if supported_formats is full and does not contain format.
4313 */
4314static void register_format(audio_format_t format,
4315 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4316 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4317 "%s: stream can not declare supporting its format %x", __func__, format);
4318}
4319/** Add sample_rate in supported_sample_rates if not already present.
4320 * @return true if sample_rate was successfully inserted or already present,
4321 * false if supported_sample_rates is full and does not contain sample_rate.
4322 */
4323static void register_sample_rate(uint32_t sample_rate,
4324 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4325 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4326 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4327}
4328
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004329static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4330{
4331 uint32_t high = num1, low = num2, temp = 0;
4332
4333 if (!num1 || !num2)
4334 return 0;
4335
4336 if (num1 < num2) {
4337 high = num2;
4338 low = num1;
4339 }
4340
4341 while (low != 0) {
4342 temp = low;
4343 low = high % low;
4344 high = temp;
4345 }
4346 return (num1 * num2)/high;
4347}
4348
4349static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4350{
4351 uint32_t remainder = 0;
4352
4353 if (!multiplier)
4354 return num;
4355
4356 remainder = num % multiplier;
4357 if (remainder)
4358 num += (multiplier - remainder);
4359
4360 return num;
4361}
4362
Aalique Grahame22e49102018-12-18 14:23:57 -08004363static size_t get_stream_buffer_size(size_t duration_ms,
4364 uint32_t sample_rate,
4365 audio_format_t format,
4366 int channel_count,
4367 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368{
4369 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004370 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371
Aalique Grahame22e49102018-12-18 14:23:57 -08004372 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004373 if (is_low_latency)
4374 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304375
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004376 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004377 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378
Ralf Herzbd08d632018-09-28 15:50:49 +02004379 /* make sure the size is multiple of 32 bytes and additionally multiple of
4380 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004381 * At 48 kHz mono 16-bit PCM:
4382 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4383 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004384 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004385 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004386 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004387
4388 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004389}
4390
Aalique Grahame22e49102018-12-18 14:23:57 -08004391static size_t get_input_buffer_size(uint32_t sample_rate,
4392 audio_format_t format,
4393 int channel_count,
4394 bool is_low_latency)
4395{
4396 /* Don't know if USB HIFI in this context so use true to be conservative */
4397 if (check_input_parameters(sample_rate, format, channel_count,
4398 true /*is_usb_hifi */) != 0)
4399 return 0;
4400
4401 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4402 sample_rate,
4403 format,
4404 channel_count,
4405 is_low_latency);
4406}
4407
Derek Chenf6318be2017-06-12 17:16:24 -04004408size_t get_output_period_size(uint32_t sample_rate,
4409 audio_format_t format,
4410 int channel_count,
4411 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304412{
4413 size_t size = 0;
4414 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4415
4416 if ((duration == 0) || (sample_rate == 0) ||
4417 (bytes_per_sample == 0) || (channel_count == 0)) {
4418 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4419 bytes_per_sample, channel_count);
4420 return -EINVAL;
4421 }
4422
4423 size = (sample_rate *
4424 duration *
4425 bytes_per_sample *
4426 channel_count) / 1000;
4427 /*
4428 * To have same PCM samples for all channels, the buffer size requires to
4429 * be multiple of (number of channels * bytes per sample)
4430 * For writes to succeed, the buffer must be written at address which is multiple of 32
4431 */
4432 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4433
4434 return (size/(channel_count * bytes_per_sample));
4435}
4436
Zhou Song48453a02018-01-10 17:50:59 +08004437static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304438{
4439 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004440 uint64_t written_frames = 0;
4441 uint64_t kernel_frames = 0;
4442 uint64_t dsp_frames = 0;
4443 uint64_t signed_frames = 0;
4444 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304445
4446 /* This adjustment accounts for buffering after app processor.
4447 * It is based on estimated DSP latency per use case, rather than exact.
4448 */
George Gao9ba8a142020-07-23 14:30:03 -07004449 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004450 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304451
Zhou Song48453a02018-01-10 17:50:59 +08004452 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004453 written_frames = out->written /
4454 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4455
Ashish Jain5106d362016-05-11 19:23:33 +05304456 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4457 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4458 * hence only estimate.
4459 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004460 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4461 kernel_frames = kernel_buffer_size /
4462 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304463
Weiyin Jiang4813da12020-05-28 00:37:28 +08004464 if (written_frames >= (kernel_frames + dsp_frames))
4465 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304466
Zhou Song48453a02018-01-10 17:50:59 +08004467 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304468 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004469 if (timestamp != NULL )
4470 *timestamp = out->writeAt;
4471 } else if (timestamp != NULL) {
4472 clock_gettime(CLOCK_MONOTONIC, timestamp);
4473 }
4474 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304475
Weiyin Jiang4813da12020-05-28 00:37:28 +08004476 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4477 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304478
4479 return actual_frames_rendered;
4480}
4481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
4485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004486 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487}
4488
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004489static int out_set_sample_rate(struct audio_stream *stream __unused,
4490 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491{
4492 return -ENOSYS;
4493}
4494
4495static size_t out_get_buffer_size(const struct audio_stream *stream)
4496{
4497 struct stream_out *out = (struct stream_out *)stream;
4498
Varun Balaraje49253e2017-07-06 19:48:56 +05304499 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304500 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304501 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304502 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4503 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4504 else
4505 return out->compr_config.fragment_size;
4506 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004507 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304508 else if (is_offload_usecase(out->usecase) &&
4509 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304510 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004511
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004512 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004513 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514}
4515
4516static uint32_t out_get_channels(const struct audio_stream *stream)
4517{
4518 struct stream_out *out = (struct stream_out *)stream;
4519
4520 return out->channel_mask;
4521}
4522
4523static audio_format_t out_get_format(const struct audio_stream *stream)
4524{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 struct stream_out *out = (struct stream_out *)stream;
4526
4527 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004528}
4529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004530static int out_set_format(struct audio_stream *stream __unused,
4531 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532{
4533 return -ENOSYS;
4534}
4535
4536static int out_standby(struct audio_stream *stream)
4537{
4538 struct stream_out *out = (struct stream_out *)stream;
4539 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004540 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004541
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304542 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4543 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004545 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004547 if (adev->adm_deregister_stream)
4548 adev->adm_deregister_stream(adev->adm_data, out->handle);
4549
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004550 if (is_offload_usecase(out->usecase)) {
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004551 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004552 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004553
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004554 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004556 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4557 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304558 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004559 pthread_mutex_unlock(&adev->lock);
4560 pthread_mutex_unlock(&out->lock);
4561 ALOGD("VOIP output entered standby");
4562 return 0;
4563 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004564 if (out->pcm) {
4565 pcm_close(out->pcm);
4566 out->pcm = NULL;
4567 }
Meng Wanga09da002020-04-20 12:56:04 +08004568 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4569 if (adev->haptic_pcm) {
4570 pcm_close(adev->haptic_pcm);
4571 adev->haptic_pcm = NULL;
4572 }
4573
4574 if (adev->haptic_buffer != NULL) {
4575 free(adev->haptic_buffer);
4576 adev->haptic_buffer = NULL;
4577 adev->haptic_buffer_size = 0;
4578 }
4579 adev->haptic_pcm_device_id = 0;
4580 }
4581
Haynes Mathew George16081042017-05-31 17:16:49 -07004582 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4583 do_stop = out->playback_started;
4584 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004585
4586 if (out->mmap_shared_memory_fd >= 0) {
4587 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4588 __func__, out->mmap_shared_memory_fd);
4589 close(out->mmap_shared_memory_fd);
4590 out->mmap_shared_memory_fd = -1;
4591 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004592 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004593 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004594 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304595 out->send_next_track_params = false;
4596 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004597 out->gapless_mdata.encoder_delay = 0;
4598 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004599 if (out->compr != NULL) {
4600 compress_close(out->compr);
4601 out->compr = NULL;
4602 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004603 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004604 if (do_stop) {
4605 stop_output_stream(out);
4606 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304607 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004608 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004609 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610 }
4611 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304612 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 return 0;
4614}
4615
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304616static int out_on_error(struct audio_stream *stream)
4617{
4618 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004619 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304620
4621 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004622 // always send CMD_ERROR for offload streams, this
4623 // is needed e.g. when SSR happens within compress_open
4624 // since the stream is active, offload_callback_thread is also active.
4625 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4626 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004627 }
4628 pthread_mutex_unlock(&out->lock);
4629
4630 status = out_standby(&out->stream.common);
4631
4632 lock_output_stream(out);
4633 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004634 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304635 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304636
4637 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4638 ALOGD("Setting previous card status if offline");
4639 out->prev_card_status_offline = true;
4640 }
4641
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304642 pthread_mutex_unlock(&out->lock);
4643
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004644 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304645}
4646
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304647/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004648 * standby implementation without locks, assumes that the callee already
4649 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304650 */
4651int out_standby_l(struct audio_stream *stream)
4652{
4653 struct stream_out *out = (struct stream_out *)stream;
4654 struct audio_device *adev = out->dev;
4655
4656 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4657 stream, out->usecase, use_case_table[out->usecase]);
4658
4659 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004660 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304661 if (adev->adm_deregister_stream)
4662 adev->adm_deregister_stream(adev->adm_data, out->handle);
4663
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004664 if (is_offload_usecase(out->usecase)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304665 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004666 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304667
4668 out->standby = true;
4669 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4670 voice_extn_compress_voip_close_output_stream(stream);
4671 out->started = 0;
4672 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004673 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304674 return 0;
4675 } else if (!is_offload_usecase(out->usecase)) {
4676 if (out->pcm) {
4677 pcm_close(out->pcm);
4678 out->pcm = NULL;
4679 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004680 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4681 if (adev->haptic_pcm) {
4682 pcm_close(adev->haptic_pcm);
4683 adev->haptic_pcm = NULL;
4684 }
4685
4686 if (adev->haptic_buffer != NULL) {
4687 free(adev->haptic_buffer);
4688 adev->haptic_buffer = NULL;
4689 adev->haptic_buffer_size = 0;
4690 }
4691 adev->haptic_pcm_device_id = 0;
4692 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304693 } else {
4694 ALOGD("copl(%p):standby", out);
4695 out->send_next_track_params = false;
4696 out->is_compr_metadata_avail = false;
4697 out->gapless_mdata.encoder_delay = 0;
4698 out->gapless_mdata.encoder_padding = 0;
4699 if (out->compr != NULL) {
4700 compress_close(out->compr);
4701 out->compr = NULL;
4702 }
4703 }
4704 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004705 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304706 }
4707 ALOGD("%s: exit", __func__);
4708 return 0;
4709}
4710
Aalique Grahame22e49102018-12-18 14:23:57 -08004711static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712{
Aalique Grahame22e49102018-12-18 14:23:57 -08004713 struct stream_out *out = (struct stream_out *)stream;
4714
4715 // We try to get the lock for consistency,
4716 // but it isn't necessary for these variables.
4717 // If we're not in standby, we may be blocked on a write.
4718 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4719 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4720 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4721
Andy Hunga1f48fa2019-07-01 18:14:53 -07004722 char buffer[256]; // for statistics formatting
4723 if (!is_offload_usecase(out->usecase)) {
4724 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4725 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4726 }
4727
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004728 if (out->start_latency_ms.n > 0) {
4729 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4730 dprintf(fd, " Start latency ms: %s\n", buffer);
4731 }
4732
Aalique Grahame22e49102018-12-18 14:23:57 -08004733 if (locked) {
4734 pthread_mutex_unlock(&out->lock);
4735 }
4736
4737 // dump error info
4738 (void)error_log_dump(
4739 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741 return 0;
4742}
4743
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004744static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4745{
4746 int ret = 0;
4747 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004748
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004749 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004750 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004751 return -EINVAL;
4752 }
4753
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304754 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004755
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004756 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4757 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304758 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004759 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004760 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4761 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304762 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004763 }
4764
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004765 ALOGV("%s new encoder delay %u and padding %u", __func__,
4766 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4767
4768 return 0;
4769}
4770
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004771static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4772{
4773 return out == adev->primary_output || out == adev->voice_tx_output;
4774}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004775
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304776// note: this call is safe only if the stream_cb is
4777// removed first in close_output_stream (as is done now).
4778static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4779{
4780 if (!stream || !parms)
4781 return;
4782
4783 struct stream_out *out = (struct stream_out *)stream;
4784 struct audio_device *adev = out->dev;
4785
4786 card_status_t status;
4787 int card;
4788 if (parse_snd_card_status(parms, &card, &status) < 0)
4789 return;
4790
4791 pthread_mutex_lock(&adev->lock);
4792 bool valid_cb = (card == adev->snd_card);
4793 pthread_mutex_unlock(&adev->lock);
4794
4795 if (!valid_cb)
4796 return;
4797
4798 lock_output_stream(out);
4799 if (out->card_status != status)
4800 out->card_status = status;
4801 pthread_mutex_unlock(&out->lock);
4802
4803 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4804 use_case_table[out->usecase],
4805 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4806
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304807 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304808 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304809 if (voice_is_call_state_active(adev) &&
4810 out == adev->primary_output) {
4811 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4812 pthread_mutex_lock(&adev->lock);
4813 voice_stop_call(adev);
4814 adev->mode = AUDIO_MODE_NORMAL;
4815 pthread_mutex_unlock(&adev->lock);
4816 }
4817 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304818 return;
4819}
4820
Kevin Rocardfce19002017-08-07 19:21:36 -07004821static int get_alive_usb_card(struct str_parms* parms) {
4822 int card;
4823 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4824 !audio_extn_usb_alive(card)) {
4825 return card;
4826 }
4827 return -ENODEV;
4828}
4829
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004830int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004831 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832{
4833 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004834 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004835 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004836 bool bypass_a2dp = false;
4837 bool reconfig = false;
4838 unsigned long service_interval = 0;
4839
4840 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004841 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4842
4843 list_init(&new_devices);
4844 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004845
4846 lock_output_stream(out);
4847 pthread_mutex_lock(&adev->lock);
4848
4849 /*
4850 * When HDMI cable is unplugged the music playback is paused and
4851 * the policy manager sends routing=0. But the audioflinger continues
4852 * to write data until standby time (3sec). As the HDMI core is
4853 * turned off, the write gets blocked.
4854 * Avoid this by routing audio to speaker until standby.
4855 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004856 if (is_single_device_type_equal(&out->device_list,
4857 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004858 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004859 !audio_extn_passthru_is_passthrough_stream(out) &&
4860 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004861 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004862 }
4863 /*
4864 * When A2DP is disconnected the
4865 * music playback is paused and the policy manager sends routing=0
4866 * But the audioflinger continues to write data until standby time
4867 * (3sec). As BT is turned off, the write gets blocked.
4868 * Avoid this by routing audio to speaker until standby.
4869 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004870 if (is_a2dp_out_device_type(&out->device_list) &&
4871 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004872 !audio_extn_a2dp_source_is_ready() &&
4873 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004874 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004875 }
4876 /*
4877 * When USB headset is disconnected the music platback paused
4878 * and the policy manager send routing=0. But if the USB is connected
4879 * back before the standby time, AFE is not closed and opened
4880 * when USB is connected back. So routing to speker will guarantee
4881 * AFE reconfiguration and AFE will be opend once USB is connected again
4882 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004883 if (is_usb_out_device_type(&out->device_list) &&
4884 list_empty(&new_devices) &&
4885 !audio_extn_usb_connected(NULL)) {
4886 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4887 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004888 /* To avoid a2dp to sco overlapping / BT device improper state
4889 * check with BT lib about a2dp streaming support before routing
4890 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004891 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004892 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004893 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4894 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004895 //combo usecase just by pass a2dp
4896 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4897 bypass_a2dp = true;
4898 } else {
4899 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4900 /* update device to a2dp and don't route as BT returned error
4901 * However it is still possible a2dp routing called because
4902 * of current active device disconnection (like wired headset)
4903 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004904 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004905 pthread_mutex_unlock(&adev->lock);
4906 pthread_mutex_unlock(&out->lock);
4907 goto error;
4908 }
4909 }
4910 }
4911
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004912 // Workaround: If routing to an non existing usb device, fail gracefully
4913 // The routing request will otherwise block during 10 second
4914 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004915 if (is_usb_out_device_type(&new_devices)) {
4916 struct str_parms *parms =
4917 str_parms_create_str(get_usb_device_address(&new_devices));
4918 if (!parms)
4919 goto error;
4920 if ((card = get_alive_usb_card(parms)) >= 0) {
4921 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4922 pthread_mutex_unlock(&adev->lock);
4923 pthread_mutex_unlock(&out->lock);
4924 str_parms_destroy(parms);
4925 ret = -ENOSYS;
4926 goto error;
4927 }
4928 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004929 }
4930
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004931 // Workaround: If routing to an non existing hdmi device, fail gracefully
4932 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4933 (platform_get_edid_info_v2(adev->platform,
4934 out->extconn.cs.controller,
4935 out->extconn.cs.stream) != 0)) {
4936 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4937 pthread_mutex_unlock(&adev->lock);
4938 pthread_mutex_unlock(&out->lock);
4939 ret = -ENOSYS;
4940 goto error;
4941 }
4942
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004943 /*
4944 * select_devices() call below switches all the usecases on the same
4945 * backend to the new device. Refer to check_usecases_codec_backend() in
4946 * the select_devices(). But how do we undo this?
4947 *
4948 * For example, music playback is active on headset (deep-buffer usecase)
4949 * and if we go to ringtones and select a ringtone, low-latency usecase
4950 * will be started on headset+speaker. As we can't enable headset+speaker
4951 * and headset devices at the same time, select_devices() switches the music
4952 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4953 * So when the ringtone playback is completed, how do we undo the same?
4954 *
4955 * We are relying on the out_set_parameters() call on deep-buffer output,
4956 * once the ringtone playback is ended.
4957 * NOTE: We should not check if the current devices are same as new devices.
4958 * Because select_devices() must be called to switch back the music
4959 * playback to headset.
4960 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004961 if (!list_empty(&new_devices)) {
4962 bool same_dev = compare_devices(&out->device_list, &new_devices);
4963 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004964
4965 if (output_drives_call(adev, out)) {
4966 if (!voice_is_call_state_active(adev)) {
4967 if (adev->mode == AUDIO_MODE_IN_CALL) {
4968 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004969 ret = voice_start_call(adev);
4970 }
4971 } else {
4972 adev->current_call_output = out;
4973 voice_update_devices_for_all_voice_usecases(adev);
4974 }
4975 }
4976
Mingshu Pang60536d72020-09-09 15:28:22 +08004977 if (is_usb_out_device_type(&out->device_list)) {
4978 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4979 audio_extn_usb_set_service_interval(true /*playback*/,
4980 service_interval,
4981 &reconfig);
4982 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4983 }
4984
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004985 if (!out->standby) {
4986 if (!same_dev) {
4987 ALOGV("update routing change");
4988 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4989 adev->perf_lock_opts,
4990 adev->perf_lock_opts_size);
4991 if (adev->adm_on_routing_change)
4992 adev->adm_on_routing_change(adev->adm_data,
4993 out->handle);
4994 }
4995 if (!bypass_a2dp) {
4996 select_devices(adev, out->usecase);
4997 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004998 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4999 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005000 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005001 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005002 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005003 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005004 }
5005
5006 if (!same_dev) {
5007 // on device switch force swap, lower functions will make sure
5008 // to check if swap is allowed or not.
5009 platform_set_swap_channels(adev, true);
5010 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5011 }
Zhou Song1f93fa52020-11-20 13:57:39 +08005012 pthread_mutex_lock(&out->latch_lock);
5013 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5014 if (out->a2dp_muted) {
5015 out->a2dp_muted = false;
5016 if (is_offload_usecase(out->usecase))
5017 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5018 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5019 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005020 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005021 }
Zhou Song1f93fa52020-11-20 13:57:39 +08005022 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5023 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5024 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005025 }
5026 }
5027
5028 pthread_mutex_unlock(&adev->lock);
5029 pthread_mutex_unlock(&out->lock);
5030
5031 /*handles device and call state changes*/
5032 audio_extn_extspk_update(adev->extspk);
5033
5034error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005035 ALOGV("%s: exit: code(%d)", __func__, ret);
5036 return ret;
5037}
5038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5040{
5041 struct stream_out *out = (struct stream_out *)stream;
5042 struct audio_device *adev = out->dev;
5043 struct str_parms *parms;
5044 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005045 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005046 int ext_controller = -1;
5047 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005048
sangwoobc677242013-08-08 16:53:43 +09005049 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005050 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005051 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305052 if (!parms)
5053 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005054
5055 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5056 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005057 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005058 out->extconn.cs.controller = ext_controller;
5059 out->extconn.cs.stream = ext_stream;
5060 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5061 use_case_table[out->usecase], out->extconn.cs.controller,
5062 out->extconn.cs.stream);
5063 }
5064
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005065 if (out == adev->primary_output) {
5066 pthread_mutex_lock(&adev->lock);
5067 audio_extn_set_parameters(adev, parms);
5068 pthread_mutex_unlock(&adev->lock);
5069 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005070 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005071 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005072 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005073
5074 audio_extn_dts_create_state_notifier_node(out->usecase);
5075 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5076 popcount(out->channel_mask),
5077 out->playback_started);
5078
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005079 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005080 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005081
Surendar Karkaf51b5842018-04-26 11:28:38 +05305082 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5083 sizeof(value));
5084 if (err >= 0) {
5085 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5086 audio_extn_send_dual_mono_mixing_coefficients(out);
5087 }
5088
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305089 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5090 if (err >= 0) {
5091 strlcpy(out->profile, value, sizeof(out->profile));
5092 ALOGV("updating stream profile with value '%s'", out->profile);
5093 lock_output_stream(out);
5094 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5095 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005096 &out->device_list, out->flags,
5097 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305098 out->sample_rate, out->bit_width,
5099 out->channel_mask, out->profile,
5100 &out->app_type_cfg);
5101 pthread_mutex_unlock(&out->lock);
5102 }
5103
Alexy Joseph98988832017-01-13 14:56:59 -08005104 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005105 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5106 // and vendor.audio.hal.output.suspend.supported is set to true
5107 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005108 //check suspend parameter only for low latency and if the property
5109 //is enabled
5110 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5111 ALOGI("%s: got suspend_playback %s", __func__, value);
5112 lock_output_stream(out);
5113 if (!strncmp(value, "false", 5)) {
5114 //suspend_playback=false is supposed to set QOS value back to 75%
5115 //the mixer control sent with value Enable will achieve that
5116 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5117 } else if (!strncmp (value, "true", 4)) {
5118 //suspend_playback=true is supposed to remove QOS value
5119 //resetting the mixer control will set the default value
5120 //for the mixer control which is Disable and this removes the QOS vote
5121 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5122 } else {
5123 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5124 " got %s", __func__, value);
5125 ret = -1;
5126 }
5127
5128 if (ret != 0) {
5129 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5130 __func__, out->pm_qos_mixer_path, ret);
5131 }
5132
5133 pthread_mutex_unlock(&out->lock);
5134 }
5135 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005136
Alexy Joseph98988832017-01-13 14:56:59 -08005137 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005138 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305139error:
Eric Laurent994a6932013-07-17 11:51:42 -07005140 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141 return ret;
5142}
5143
Paul McLeana50b7332018-12-17 08:24:21 -07005144static int in_set_microphone_direction(const struct audio_stream_in *stream,
5145 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005146 struct stream_in *in = (struct stream_in *)stream;
5147
5148 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5149
5150 in->direction = dir;
5151
5152 if (in->standby)
5153 return 0;
5154
5155 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005156}
5157
5158static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005159 struct stream_in *in = (struct stream_in *)stream;
5160
5161 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5162
5163 if (zoom > 1.0 || zoom < -1.0)
5164 return -EINVAL;
5165
5166 in->zoom = zoom;
5167
5168 if (in->standby)
5169 return 0;
5170
5171 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005172}
5173
5174
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005175static bool stream_get_parameter_channels(struct str_parms *query,
5176 struct str_parms *reply,
5177 audio_channel_mask_t *supported_channel_masks) {
5178 int ret = -1;
5179 char value[512];
5180 bool first = true;
5181 size_t i, j;
5182
5183 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5184 ret = 0;
5185 value[0] = '\0';
5186 i = 0;
5187 while (supported_channel_masks[i] != 0) {
5188 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5189 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5190 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305191 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005192
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305193 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005194 first = false;
5195 break;
5196 }
5197 }
5198 i++;
5199 }
5200 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5201 }
5202 return ret == 0;
5203}
5204
5205static bool stream_get_parameter_formats(struct str_parms *query,
5206 struct str_parms *reply,
5207 audio_format_t *supported_formats) {
5208 int ret = -1;
5209 char value[256];
5210 size_t i, j;
5211 bool first = true;
5212
5213 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5214 ret = 0;
5215 value[0] = '\0';
5216 i = 0;
5217 while (supported_formats[i] != 0) {
5218 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5219 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5220 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305221 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005222 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305223 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005224 first = false;
5225 break;
5226 }
5227 }
5228 i++;
5229 }
5230 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5231 }
5232 return ret == 0;
5233}
5234
5235static bool stream_get_parameter_rates(struct str_parms *query,
5236 struct str_parms *reply,
5237 uint32_t *supported_sample_rates) {
5238
5239 int i;
5240 char value[256];
5241 int ret = -1;
5242 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5243 ret = 0;
5244 value[0] = '\0';
5245 i=0;
5246 int cursor = 0;
5247 while (supported_sample_rates[i]) {
5248 int avail = sizeof(value) - cursor;
5249 ret = snprintf(value + cursor, avail, "%s%d",
5250 cursor > 0 ? "|" : "",
5251 supported_sample_rates[i]);
5252 if (ret < 0 || ret >= avail) {
5253 // if cursor is at the last element of the array
5254 // overwrite with \0 is duplicate work as
5255 // snprintf already put a \0 in place.
5256 // else
5257 // we had space to write the '|' at value[cursor]
5258 // (which will be overwritten) or no space to fill
5259 // the first element (=> cursor == 0)
5260 value[cursor] = '\0';
5261 break;
5262 }
5263 cursor += ret;
5264 ++i;
5265 }
5266 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5267 value);
5268 }
5269 return ret >= 0;
5270}
5271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5273{
5274 struct stream_out *out = (struct stream_out *)stream;
5275 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005276 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005277 char value[256];
5278 struct str_parms *reply = str_parms_create();
5279 size_t i, j;
5280 int ret;
5281 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005282
5283 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005284 if (reply) {
5285 str_parms_destroy(reply);
5286 }
5287 if (query) {
5288 str_parms_destroy(query);
5289 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005290 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5291 return NULL;
5292 }
5293
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005294 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5296 if (ret >= 0) {
5297 value[0] = '\0';
5298 i = 0;
5299 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005300 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5301 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005303 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005305 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 first = false;
5307 break;
5308 }
5309 }
5310 i++;
5311 }
5312 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5313 str = str_parms_to_str(reply);
5314 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005315 voice_extn_out_get_parameters(out, query, reply);
5316 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005317 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005318
Alexy Joseph62142aa2015-11-16 15:10:34 -08005319
5320 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5321 if (ret >= 0) {
5322 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305323 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5324 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005325 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305326 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005327 } else {
5328 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305329 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005330 }
5331 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005332 if (str)
5333 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005334 str = str_parms_to_str(reply);
5335 }
5336
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005337 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5338 if (ret >= 0) {
5339 value[0] = '\0';
5340 i = 0;
5341 first = true;
5342 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005343 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5344 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005345 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005346 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005347 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005348 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005349 first = false;
5350 break;
5351 }
5352 }
5353 i++;
5354 }
5355 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005356 if (str)
5357 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005358 str = str_parms_to_str(reply);
5359 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005360
5361 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5362 if (ret >= 0) {
5363 value[0] = '\0';
5364 i = 0;
5365 first = true;
5366 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005367 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5368 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005369 if (!first) {
5370 strlcat(value, "|", sizeof(value));
5371 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005372 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005373 first = false;
5374 break;
5375 }
5376 }
5377 i++;
5378 }
5379 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5380 if (str)
5381 free(str);
5382 str = str_parms_to_str(reply);
5383 }
5384
Alexy Joseph98988832017-01-13 14:56:59 -08005385 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5386 //only low latency track supports suspend_resume
5387 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005388 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005389 if (str)
5390 free(str);
5391 str = str_parms_to_str(reply);
5392 }
5393
5394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395 str_parms_destroy(query);
5396 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005397 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005398 return str;
5399}
5400
5401static uint32_t out_get_latency(const struct audio_stream_out *stream)
5402{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005403 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005405 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005406
Alexy Josephaa54c872014-12-03 02:46:47 -08005407 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305408 lock_output_stream(out);
5409 latency = audio_extn_utils_compress_get_dsp_latency(out);
5410 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005411 } else if ((out->realtime) ||
5412 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005413 // since the buffer won't be filled up faster than realtime,
5414 // return a smaller number
5415 if (out->config.rate)
5416 period_ms = (out->af_period_multiplier * out->config.period_size *
5417 1000) / (out->config.rate);
5418 else
5419 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005420 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005421 } else {
5422 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005423 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005424 }
5425
Zhou Songd2537a02020-06-11 22:04:46 +08005426 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005427 latency += audio_extn_a2dp_get_encoder_latency();
5428
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305429 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005430 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431}
5432
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305433static float AmpToDb(float amplification)
5434{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305435 float db = DSD_VOLUME_MIN_DB;
5436 if (amplification > 0) {
5437 db = 20 * log10(amplification);
5438 if(db < DSD_VOLUME_MIN_DB)
5439 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305440 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305441 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305442}
5443
Arun Mirpuri5d170872019-03-26 13:21:31 -07005444static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5445 float right)
5446{
5447 struct stream_out *out = (struct stream_out *)stream;
5448 long volume = 0;
5449 char mixer_ctl_name[128] = "";
5450 struct audio_device *adev = out->dev;
5451 struct mixer_ctl *ctl = NULL;
5452 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5453 PCM_PLAYBACK);
5454
5455 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5456 "Playback %d Volume", pcm_device_id);
5457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5458 if (!ctl) {
5459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5460 __func__, mixer_ctl_name);
5461 return -EINVAL;
5462 }
5463 if (left != right)
5464 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5465 __func__, left, right);
5466 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5467 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5468 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5469 __func__, mixer_ctl_name, volume);
5470 return -EINVAL;
5471 }
5472 return 0;
5473}
5474
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305475static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5476 float right)
5477{
5478 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305479 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305480 char mixer_ctl_name[128];
5481 struct audio_device *adev = out->dev;
5482 struct mixer_ctl *ctl;
5483 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5484 PCM_PLAYBACK);
5485
5486 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5487 "Compress Playback %d Volume", pcm_device_id);
5488 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5489 if (!ctl) {
5490 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5491 __func__, mixer_ctl_name);
5492 return -EINVAL;
5493 }
5494 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5495 __func__, mixer_ctl_name, left, right);
5496 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5497 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5498 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5499
5500 return 0;
5501}
5502
Zhou Song2b8f28f2017-09-11 10:51:38 +08005503static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5504 float right)
5505{
5506 struct stream_out *out = (struct stream_out *)stream;
5507 char mixer_ctl_name[] = "App Type Gain";
5508 struct audio_device *adev = out->dev;
5509 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305510 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005511
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005512 if (!is_valid_volume(left, right)) {
5513 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5514 __func__, left, right);
5515 return -EINVAL;
5516 }
5517
Zhou Song2b8f28f2017-09-11 10:51:38 +08005518 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5519 if (!ctl) {
5520 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5521 __func__, mixer_ctl_name);
5522 return -EINVAL;
5523 }
5524
5525 set_values[0] = 0; //0: Rx Session 1:Tx Session
5526 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305527 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5528 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005529
5530 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5531 return 0;
5532}
5533
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305534static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5535 float right)
5536{
5537 struct stream_out *out = (struct stream_out *)stream;
5538 /* Volume control for pcm playback */
5539 if (left != right) {
5540 return -EINVAL;
5541 } else {
5542 char mixer_ctl_name[128];
5543 struct audio_device *adev = out->dev;
5544 struct mixer_ctl *ctl;
5545 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5546 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5547 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5548 if (!ctl) {
5549 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5550 return -EINVAL;
5551 }
5552
5553 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5554 int ret = mixer_ctl_set_value(ctl, 0, volume);
5555 if (ret < 0) {
5556 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5557 return -EINVAL;
5558 }
5559
5560 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5561
5562 return 0;
5563 }
5564}
5565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005566static int out_set_volume(struct audio_stream_out *stream, float left,
5567 float right)
5568{
Eric Laurenta9024de2013-04-04 09:19:12 -07005569 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005570 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305571 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005572
Arun Mirpuri5d170872019-03-26 13:21:31 -07005573 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005574 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5575 /* only take left channel into account: the API is for stereo anyway */
5576 out->muted = (left == 0.0f);
5577 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005578 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305579 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005580 /*
5581 * Set mute or umute on HDMI passthrough stream.
5582 * Only take left channel into account.
5583 * Mute is 0 and unmute 1
5584 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305585 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305586 } else if (out->format == AUDIO_FORMAT_DSD){
5587 char mixer_ctl_name[128] = "DSD Volume";
5588 struct audio_device *adev = out->dev;
5589 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5590
5591 if (!ctl) {
5592 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5593 __func__, mixer_ctl_name);
5594 return -EINVAL;
5595 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305596 volume[0] = (long)(AmpToDb(left));
5597 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305598 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5599 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005600 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005601 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005602 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5603 struct listnode *node = NULL;
5604 list_for_each(node, &adev->active_outputs_list) {
5605 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5606 streams_output_ctxt_t,
5607 list);
5608 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5609 out->volume_l = out_ctxt->output->volume_l;
5610 out->volume_r = out_ctxt->output->volume_r;
5611 }
5612 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005613 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005614 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005615 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5616 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005617 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005618 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005619 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005620 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005621 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5622 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305623 ret = out_set_compr_volume(stream, left, right);
5624 out->volume_l = left;
5625 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005626 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305627 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005628 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005629 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005630 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5631 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song1f93fa52020-11-20 13:57:39 +08005632 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005633 if (!out->standby) {
5634 audio_extn_utils_send_app_type_gain(out->dev,
5635 out->app_type_cfg.app_type,
5636 &out->app_type_cfg.gain[0]);
Zhou Song1f93fa52020-11-20 13:57:39 +08005637 if (!out->a2dp_muted)
5638 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005639 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005640 out->volume_l = left;
5641 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005642 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005643 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005644 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5645 ALOGV("%s: MMAP set volume called", __func__);
5646 if (!out->standby)
5647 ret = out_set_mmap_volume(stream, left, right);
5648 out->volume_l = left;
5649 out->volume_r = right;
5650 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305651 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305652 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5653 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Song1f93fa52020-11-20 13:57:39 +08005654 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305655 /* Volume control for pcm playback */
Zhou Song1f93fa52020-11-20 13:57:39 +08005656 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305657 ret = out_set_pcm_volume(stream, left, right);
5658 else
5659 out->apply_volume = true;
5660
5661 out->volume_l = left;
5662 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005663 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305664 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005665 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5666 ALOGV("%s: bus device set volume called", __func__);
Zhou Song1f93fa52020-11-20 13:57:39 +08005667 pthread_mutex_lock(&out->latch_lock);
5668 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005669 ret = out_set_pcm_volume(stream, left, right);
5670 out->volume_l = left;
5671 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005672 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005673 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005674 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676 return -ENOSYS;
5677}
5678
Zhou Songc9672822017-08-16 16:01:39 +08005679static void update_frames_written(struct stream_out *out, size_t bytes)
5680{
5681 size_t bpf = 0;
5682
5683 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5684 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5685 bpf = 1;
5686 else if (!is_offload_usecase(out->usecase))
5687 bpf = audio_bytes_per_sample(out->format) *
5688 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005689
5690 pthread_mutex_lock(&out->position_query_lock);
5691 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005692 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005693 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5694 }
5695 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005696}
5697
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005698int split_and_write_audio_haptic_data(struct stream_out *out,
5699 const void *buffer, size_t bytes_to_write)
5700{
5701 struct audio_device *adev = out->dev;
5702
5703 int ret = 0;
5704 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5705 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5706 size_t frame_size = channel_count * bytes_per_sample;
5707 size_t frame_count = bytes_to_write / frame_size;
5708
5709 bool force_haptic_path =
5710 property_get_bool("vendor.audio.test_haptic", false);
5711
5712 // extract Haptics data from Audio buffer
5713 bool alloc_haptic_buffer = false;
5714 int haptic_channel_count = adev->haptics_config.channels;
5715 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5716 size_t audio_frame_size = frame_size - haptic_frame_size;
5717 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5718
5719 if (adev->haptic_buffer == NULL) {
5720 alloc_haptic_buffer = true;
5721 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5722 free(adev->haptic_buffer);
5723 adev->haptic_buffer_size = 0;
5724 alloc_haptic_buffer = true;
5725 }
5726
5727 if (alloc_haptic_buffer) {
5728 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005729 if(adev->haptic_buffer == NULL) {
5730 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5731 return -ENOMEM;
5732 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005733 adev->haptic_buffer_size = total_haptic_buffer_size;
5734 }
5735
5736 size_t src_index = 0, aud_index = 0, hap_index = 0;
5737 uint8_t *audio_buffer = (uint8_t *)buffer;
5738 uint8_t *haptic_buffer = adev->haptic_buffer;
5739
5740 // This is required for testing only. This works for stereo data only.
5741 // One channel is fed to audio stream and other to haptic stream for testing.
5742 if (force_haptic_path)
5743 audio_frame_size = haptic_frame_size = bytes_per_sample;
5744
5745 for (size_t i = 0; i < frame_count; i++) {
5746 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5747 audio_frame_size);
5748 aud_index += audio_frame_size;
5749 src_index += audio_frame_size;
5750
5751 if (adev->haptic_pcm)
5752 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5753 haptic_frame_size);
5754 hap_index += haptic_frame_size;
5755 src_index += haptic_frame_size;
5756
5757 // This is required for testing only.
5758 // Discard haptic channel data.
5759 if (force_haptic_path)
5760 src_index += haptic_frame_size;
5761 }
5762
5763 // write to audio pipeline
5764 ret = pcm_write(out->pcm, (void *)audio_buffer,
5765 frame_count * audio_frame_size);
5766
5767 // write to haptics pipeline
5768 if (adev->haptic_pcm)
5769 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5770 frame_count * haptic_frame_size);
5771
5772 return ret;
5773}
5774
Aalique Grahame22e49102018-12-18 14:23:57 -08005775#ifdef NO_AUDIO_OUT
5776static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5777 const void *buffer __unused, size_t bytes)
5778{
5779 struct stream_out *out = (struct stream_out *)stream;
5780
5781 /* No Output device supported other than BT for playback.
5782 * Sleep for the amount of buffer duration
5783 */
5784 lock_output_stream(out);
5785 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5786 (const struct audio_stream_out *)&out->stream) /
5787 out_get_sample_rate(&out->stream.common));
5788 pthread_mutex_unlock(&out->lock);
5789 return bytes;
5790}
5791#endif
5792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5794 size_t bytes)
5795{
5796 struct stream_out *out = (struct stream_out *)stream;
5797 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005798 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305799 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005800 const size_t frame_size = audio_stream_out_frame_size(stream);
5801 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305802 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005803 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804
Haynes Mathew George380745d2017-10-04 15:27:45 -07005805 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005806 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305807
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305808 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005809
Dhananjay Kumarac341582017-02-23 23:42:25 +05305810 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305811 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305812 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5813 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005814 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305815 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305816 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305817 ALOGD(" %s: sound card is not active/SSR state", __func__);
5818 ret= -EIO;
5819 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305820 }
5821 }
5822
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305823 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305824 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305825 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305826 goto exit;
5827 }
5828
Haynes Mathew George16081042017-05-31 17:16:49 -07005829 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5830 ret = -EINVAL;
5831 goto exit;
5832 }
5833
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005834 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305835 !out->is_iec61937_info_available) {
5836
5837 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5838 out->is_iec61937_info_available = true;
5839 } else if (audio_extn_passthru_is_enabled()) {
5840 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305841 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305842
5843 if((out->format == AUDIO_FORMAT_DTS) ||
5844 (out->format == AUDIO_FORMAT_DTS_HD)) {
5845 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5846 buffer, bytes);
5847 if (ret) {
5848 if (ret != -ENOSYS) {
5849 out->is_iec61937_info_available = false;
5850 ALOGD("iec61937 transmission info not yet updated retry");
5851 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305852 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305853 /* if stream has started and after that there is
5854 * stream config change (iec transmission config)
5855 * then trigger select_device to update backend configuration.
5856 */
5857 out->stream_config_changed = true;
5858 pthread_mutex_lock(&adev->lock);
5859 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305860 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005861 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305862 ret = -EINVAL;
5863 goto exit;
5864 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305865 pthread_mutex_unlock(&adev->lock);
5866 out->stream_config_changed = false;
5867 out->is_iec61937_info_available = true;
5868 }
5869 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305870
Meng Wang4c32fb42020-01-16 17:57:11 +08005871#ifdef AUDIO_GKI_ENABLED
5872 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5873 compr_passthr = out->compr_config.codec->reserved[0];
5874#else
5875 compr_passthr = out->compr_config.codec->compr_passthr;
5876#endif
5877
Garmond Leung317cbf12017-09-13 16:20:50 -07005878 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005879 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305880 (out->is_iec61937_info_available == true)) {
5881 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5882 ret = -EINVAL;
5883 goto exit;
5884 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305885 }
5886 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305887
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005888 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005889 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005890 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5891 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Song9ebf6792020-09-23 22:49:01 +08005892 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305893 ret = -EIO;
5894 goto exit;
5895 }
5896 }
5897 }
5898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005899 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005900 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005901 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5902
Eric Laurent150dbfe2013-02-27 14:31:02 -08005903 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005904 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5905 ret = voice_extn_compress_voip_start_output_stream(out);
5906 else
5907 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005908 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005909 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005910 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005911 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005912 goto exit;
5913 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305914 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005915 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005916
5917 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005918 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005919 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305920 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005921 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005922 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305923
5924 if ((out->is_iec61937_info_available == true) &&
5925 (audio_extn_passthru_is_passthrough_stream(out))&&
5926 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5927 ret = -EINVAL;
5928 goto exit;
5929 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305930 if (out->set_dual_mono)
5931 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005932
5933 // log startup time in ms.
5934 simple_stats_log(
5935 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005936 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005937
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005938 if (adev->is_channel_status_set == false &&
5939 compare_device_type(&out->device_list,
5940 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005941 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305942 adev->is_channel_status_set = true;
5943 }
5944
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305945 if ((adev->use_old_pspd_mix_ctrl == true) &&
5946 (out->pspd_coeff_sent == false)) {
5947 /*
5948 * Need to resend pspd coefficients after stream started for
5949 * older kernel version as it does not save the coefficients
5950 * and also stream has to be started for coeff to apply.
5951 */
5952 usecase = get_usecase_from_list(adev, out->usecase);
5953 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305954 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305955 out->pspd_coeff_sent = true;
5956 }
5957 }
5958
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005959 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005960 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005961 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005962 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005963 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5964 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305965 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5966 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005967 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305968 out->send_next_track_params = false;
5969 out->is_compr_metadata_avail = false;
5970 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005971 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305972 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305973 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005974
Ashish Jain83a6cc22016-06-28 14:34:17 +05305975 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305976 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305977 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305978 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005979 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305980 return -EINVAL;
5981 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305982 audio_format_t dst_format = out->hal_op_format;
5983 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305984
Dieter Luecking5d57def2018-09-07 14:23:37 +02005985 /* prevent division-by-zero */
5986 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5987 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5988 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5989 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305990 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005991 ATRACE_END();
5992 return -EINVAL;
5993 }
5994
Ashish Jainf1eaa582016-05-23 20:54:24 +05305995 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5996 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5997
Ashish Jain83a6cc22016-06-28 14:34:17 +05305998 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305999 dst_format,
6000 buffer,
6001 src_format,
6002 frames);
6003
Ashish Jain83a6cc22016-06-28 14:34:17 +05306004 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05306005 bytes_to_write);
6006
6007 /*Convert written bytes in audio flinger format*/
6008 if (ret > 0)
6009 ret = ((ret * format_to_bitwidth_table[out->format]) /
6010 format_to_bitwidth_table[dst_format]);
6011 }
6012 } else
6013 ret = compress_write(out->compr, buffer, bytes);
6014
Zhou Songc9672822017-08-16 16:01:39 +08006015 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6016 update_frames_written(out, bytes);
6017
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306018 if (ret < 0)
6019 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006020 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306021 /*msg to cb thread only if non blocking write is enabled*/
6022 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306023 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006024 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306025 } else if (-ENETRESET == ret) {
6026 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306027 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306028 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306029 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006030 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306031 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006032 }
Ashish Jain5106d362016-05-11 19:23:33 +05306033
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306034 /* Call compr start only when non-zero bytes of data is there to be rendered */
6035 if (!out->playback_started && ret > 0) {
6036 int status = compress_start(out->compr);
6037 if (status < 0) {
6038 ret = status;
6039 ALOGE("%s: compr start failed with err %d", __func__, errno);
6040 goto exit;
6041 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006042 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006043 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006044 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006045 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006046 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006047
6048 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6049 popcount(out->channel_mask),
6050 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006051 }
6052 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006053 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006054 return ret;
6055 } else {
6056 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006057 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006058 if (out->muted)
6059 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006060 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6061 __func__, frames, frame_size, bytes_to_write);
6062
Aalique Grahame22e49102018-12-18 14:23:57 -08006063 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006064 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6065 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6066 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006067 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6068 int16_t *src = (int16_t *)buffer;
6069 int16_t *dst = (int16_t *)buffer;
6070
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006071 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006072 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006073 "out_write called for %s use case with wrong properties",
6074 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006075
6076 /*
6077 * FIXME: this can be removed once audio flinger mixer supports
6078 * mono output
6079 */
6080
6081 /*
6082 * Code below goes over each frame in the buffer and adds both
6083 * L and R samples and then divides by 2 to convert to mono
6084 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006085 if (channel_count == 2) {
6086 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6087 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6088 }
6089 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006090 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006091 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006092
6093 // Note: since out_get_presentation_position() is called alternating with out_write()
6094 // by AudioFlinger, we can check underruns using the prior timestamp read.
6095 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6096 if (out->last_fifo_valid) {
6097 // compute drain to see if there is an underrun.
6098 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306099 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6100 int64_t frames_by_time =
6101 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6102 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006103 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6104
6105 if (underrun > 0) {
6106 simple_stats_log(&out->fifo_underruns, underrun);
6107
6108 ALOGW("%s: underrun(%lld) "
6109 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6110 __func__,
6111 (long long)out->fifo_underruns.n,
6112 (long long)frames_by_time,
6113 (long long)out->last_fifo_frames_remaining);
6114 }
6115 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6116 }
6117
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306118 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006119
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006120 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006121
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006122 if (out->config.rate)
6123 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6124 out->config.rate;
6125
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006126 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006127 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6128
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006129 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006130 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006131 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306132 out->convert_buffer != NULL) {
6133
6134 memcpy_by_audio_format(out->convert_buffer,
6135 out->hal_op_format,
6136 buffer,
6137 out->hal_ip_format,
6138 out->config.period_size * out->config.channels);
6139
6140 ret = pcm_write(out->pcm, out->convert_buffer,
6141 (out->config.period_size *
6142 out->config.channels *
6143 format_to_bitwidth_table[out->hal_op_format]));
6144 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306145 /*
6146 * To avoid underrun in DSP when the application is not pumping
6147 * data at required rate, check for the no. of bytes and ignore
6148 * pcm_write if it is less than actual buffer size.
6149 * It is a work around to a change in compress VOIP driver.
6150 */
6151 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6152 bytes < (out->config.period_size * out->config.channels *
6153 audio_bytes_per_sample(out->format))) {
6154 size_t voip_buf_size =
6155 out->config.period_size * out->config.channels *
6156 audio_bytes_per_sample(out->format);
6157 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6158 __func__, bytes, voip_buf_size);
6159 usleep(((uint64_t)voip_buf_size - bytes) *
6160 1000000 / audio_stream_out_frame_size(stream) /
6161 out_get_sample_rate(&out->stream.common));
6162 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006163 } else {
6164 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6165 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6166 else
6167 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6168 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306169 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006170
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006171 release_out_focus(out);
6172
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306173 if (ret < 0)
6174 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006175 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306176 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006178 }
6179
6180exit:
Zhou Songc9672822017-08-16 16:01:39 +08006181 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306182 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306183 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006185 pthread_mutex_unlock(&out->lock);
6186
6187 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006188 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006189 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306190 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306191 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306192 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306193 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306194 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306195 out->standby = true;
6196 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306197 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006198 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6199 /* prevent division-by-zero */
6200 uint32_t stream_size = audio_stream_out_frame_size(stream);
6201 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006202
Dieter Luecking5d57def2018-09-07 14:23:37 +02006203 if ((stream_size == 0) || (srate == 0)) {
6204 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6205 ATRACE_END();
6206 return -EINVAL;
6207 }
6208 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6209 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006210 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306211 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006212 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006213 return ret;
6214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006215 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006216 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006217 return bytes;
6218}
6219
6220static int out_get_render_position(const struct audio_stream_out *stream,
6221 uint32_t *dsp_frames)
6222{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006223 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006224
6225 if (dsp_frames == NULL)
6226 return -EINVAL;
6227
6228 *dsp_frames = 0;
6229 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006230 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306231
6232 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6233 * this operation and adev_close_output_stream(where out gets reset).
6234 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306235 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006236 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306237 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006238 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306239 return 0;
6240 }
6241
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006242 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306243 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306244 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006245 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306246 if (ret < 0)
6247 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006248 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306249 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006250 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306251 if (-ENETRESET == ret) {
6252 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306253 out->card_status = CARD_STATUS_OFFLINE;
6254 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306255 } else if(ret < 0) {
6256 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306257 ret = -EINVAL;
6258 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306259 /*
6260 * Handle corner case where compress session is closed during SSR
6261 * and timestamp is queried
6262 */
6263 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306264 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306265 } else if (out->prev_card_status_offline) {
6266 ALOGE("ERROR: previously sound card was offline,return error");
6267 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306268 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306269 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006270 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306271 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306272 pthread_mutex_unlock(&out->lock);
6273 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006274 } else if (audio_is_linear_pcm(out->format)) {
6275 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006276 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006277 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006278 } else
6279 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006280}
6281
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006282static int out_add_audio_effect(const struct audio_stream *stream __unused,
6283 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006284{
6285 return 0;
6286}
6287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006288static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6289 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290{
6291 return 0;
6292}
6293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006294static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6295 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006296{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306297 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298}
6299
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006300static int out_get_presentation_position(const struct audio_stream_out *stream,
6301 uint64_t *frames, struct timespec *timestamp)
6302{
6303 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306304 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006305 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006306
Ashish Jain5106d362016-05-11 19:23:33 +05306307 /* below piece of code is not guarded against any lock because audioFliner serializes
6308 * this operation and adev_close_output_stream( where out gets reset).
6309 */
6310 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306311 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006312 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306313 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6314 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6315 return 0;
6316 }
6317
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006318 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006319
Ashish Jain5106d362016-05-11 19:23:33 +05306320 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6321 ret = compress_get_tstamp(out->compr, &dsp_frames,
6322 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006323 // Adjustment accounts for A2dp encoder latency with offload usecases
6324 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006325 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006326 unsigned long offset =
6327 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6328 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6329 }
Ashish Jain5106d362016-05-11 19:23:33 +05306330 ALOGVV("%s rendered frames %ld sample_rate %d",
6331 __func__, dsp_frames, out->sample_rate);
6332 *frames = dsp_frames;
6333 if (ret < 0)
6334 ret = -errno;
6335 if (-ENETRESET == ret) {
6336 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306337 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306338 ret = -EINVAL;
6339 } else
6340 ret = 0;
6341 /* this is the best we can do */
6342 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006343 } else {
6344 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006345 unsigned int avail;
6346 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006347 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006348 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006349
Andy Hunga1f48fa2019-07-01 18:14:53 -07006350 if (out->kernel_buffer_size > avail) {
6351 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6352 } else {
6353 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6354 __func__, avail, out->kernel_buffer_size);
6355 avail = out->kernel_buffer_size;
6356 frames_temp = out->last_fifo_frames_remaining = 0;
6357 }
6358 out->last_fifo_valid = true;
6359 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6360
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006361 if (out->written >= frames_temp)
6362 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006363
Andy Hunga1f48fa2019-07-01 18:14:53 -07006364 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6365 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6366
Weiyin Jiangd4633762018-03-16 12:05:03 +08006367 // This adjustment accounts for buffering after app processor.
6368 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006369 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006370 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006371 if (signed_frames >= frames_temp)
6372 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006373
Weiyin Jiangd4633762018-03-16 12:05:03 +08006374 // Adjustment accounts for A2dp encoder latency with non offload usecases
6375 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006376 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006377 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6378 if (signed_frames >= frames_temp)
6379 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006380 }
6381
6382 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006383 *frames = signed_frames;
6384 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006385 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006386 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6387 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006388 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306389 *frames = out->written;
6390 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306391 if (is_offload_usecase(out->usecase))
6392 ret = -EINVAL;
6393 else
6394 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006395 }
6396 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006397 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006398 return ret;
6399}
6400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006401static int out_set_callback(struct audio_stream_out *stream,
6402 stream_callback_t callback, void *cookie)
6403{
6404 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006405 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006406
6407 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006408 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006409 out->client_callback = callback;
6410 out->client_cookie = cookie;
6411 if (out->adsp_hdlr_stream_handle) {
6412 ret = audio_extn_adsp_hdlr_stream_set_callback(
6413 out->adsp_hdlr_stream_handle,
6414 callback,
6415 cookie);
6416 if (ret)
6417 ALOGW("%s:adsp hdlr callback registration failed %d",
6418 __func__, ret);
6419 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006420 pthread_mutex_unlock(&out->lock);
6421 return 0;
6422}
6423
6424static int out_pause(struct audio_stream_out* stream)
6425{
6426 struct stream_out *out = (struct stream_out *)stream;
6427 int status = -ENOSYS;
6428 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006429 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006430 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306431 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006432 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006433 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006434 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306435 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306436 status = compress_pause(out->compr);
6437
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006438 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006439
Mingming Yin21854652016-04-13 11:54:02 -07006440 if (audio_extn_passthru_is_active()) {
6441 ALOGV("offload use case, pause passthru");
6442 audio_extn_passthru_on_pause(out);
6443 }
6444
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306445 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006446 audio_extn_dts_notify_playback_state(out->usecase, 0,
6447 out->sample_rate, popcount(out->channel_mask),
6448 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006449 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006450 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006451 pthread_mutex_unlock(&out->lock);
6452 }
6453 return status;
6454}
6455
6456static int out_resume(struct audio_stream_out* stream)
6457{
6458 struct stream_out *out = (struct stream_out *)stream;
6459 int status = -ENOSYS;
6460 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006461 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006462 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306463 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006464 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006465 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006466 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306467 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306468 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006469 }
6470 if (!status) {
6471 out->offload_state = OFFLOAD_STATE_PLAYING;
6472 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306473 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006474 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6475 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006476 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006477 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006478 pthread_mutex_unlock(&out->lock);
6479 }
6480 return status;
6481}
6482
6483static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6484{
6485 struct stream_out *out = (struct stream_out *)stream;
6486 int status = -ENOSYS;
6487 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006488 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006489 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006490 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6491 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6492 else
6493 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6494 pthread_mutex_unlock(&out->lock);
6495 }
6496 return status;
6497}
6498
6499static int out_flush(struct audio_stream_out* stream)
6500{
6501 struct stream_out *out = (struct stream_out *)stream;
6502 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006503 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006504 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006505 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006506 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006507 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
Gautam Manamfeeb1162020-12-24 14:08:04 +05306508 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006509 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006510 } else {
6511 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
Gautam Manamfeeb1162020-12-24 14:08:04 +05306512 pthread_mutex_unlock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006513 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006514 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006515 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006516 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006517 return 0;
6518 }
6519 return -ENOSYS;
6520}
6521
Haynes Mathew George16081042017-05-31 17:16:49 -07006522static int out_stop(const struct audio_stream_out* stream)
6523{
6524 struct stream_out *out = (struct stream_out *)stream;
6525 struct audio_device *adev = out->dev;
6526 int ret = -ENOSYS;
6527
6528 ALOGV("%s", __func__);
6529 pthread_mutex_lock(&adev->lock);
6530 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6531 out->playback_started && out->pcm != NULL) {
6532 pcm_stop(out->pcm);
6533 ret = stop_output_stream(out);
6534 out->playback_started = false;
6535 }
6536 pthread_mutex_unlock(&adev->lock);
6537 return ret;
6538}
6539
6540static int out_start(const struct audio_stream_out* stream)
6541{
6542 struct stream_out *out = (struct stream_out *)stream;
6543 struct audio_device *adev = out->dev;
6544 int ret = -ENOSYS;
6545
6546 ALOGV("%s", __func__);
6547 pthread_mutex_lock(&adev->lock);
6548 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6549 !out->playback_started && out->pcm != NULL) {
6550 ret = start_output_stream(out);
6551 if (ret == 0) {
6552 out->playback_started = true;
6553 }
6554 }
6555 pthread_mutex_unlock(&adev->lock);
6556 return ret;
6557}
6558
6559/*
6560 * Modify config->period_count based on min_size_frames
6561 */
6562static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6563{
6564 int periodCountRequested = (min_size_frames + config->period_size - 1)
6565 / config->period_size;
6566 int periodCount = MMAP_PERIOD_COUNT_MIN;
6567
6568 ALOGV("%s original config.period_size = %d config.period_count = %d",
6569 __func__, config->period_size, config->period_count);
6570
6571 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6572 periodCount *= 2;
6573 }
6574 config->period_count = periodCount;
6575
6576 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6577}
6578
Phil Burkfe17efd2019-03-25 10:23:35 -07006579// Read offset for the positional timestamp from a persistent vendor property.
6580// This is to workaround apparent inaccuracies in the timing information that
6581// is used by the AAudio timing model. The inaccuracies can cause glitches.
6582static int64_t get_mmap_out_time_offset() {
6583 const int32_t kDefaultOffsetMicros = 0;
6584 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006585 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006586 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6587 return mmap_time_offset_micros * (int64_t)1000;
6588}
6589
Haynes Mathew George16081042017-05-31 17:16:49 -07006590static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6591 int32_t min_size_frames,
6592 struct audio_mmap_buffer_info *info)
6593{
6594 struct stream_out *out = (struct stream_out *)stream;
6595 struct audio_device *adev = out->dev;
6596 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006597 unsigned int offset1 = 0;
6598 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006599 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006600 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006601 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006602
Arun Mirpuri5d170872019-03-26 13:21:31 -07006603 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306604 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006605 pthread_mutex_lock(&adev->lock);
6606
Sharad Sanglec6f32552018-05-04 16:15:38 +05306607 if (CARD_STATUS_OFFLINE == out->card_status ||
6608 CARD_STATUS_OFFLINE == adev->card_status) {
6609 ALOGW("out->card_status or adev->card_status offline, try again");
6610 ret = -EIO;
6611 goto exit;
6612 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306613 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006614 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6615 ret = -EINVAL;
6616 goto exit;
6617 }
6618 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6619 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6620 ret = -ENOSYS;
6621 goto exit;
6622 }
6623 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6624 if (out->pcm_device_id < 0) {
6625 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6626 __func__, out->pcm_device_id, out->usecase);
6627 ret = -EINVAL;
6628 goto exit;
6629 }
6630
6631 adjust_mmap_period_count(&out->config, min_size_frames);
6632
Arun Mirpuri5d170872019-03-26 13:21:31 -07006633 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006634 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6635 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6636 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306637 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306638 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6639 out->card_status = CARD_STATUS_OFFLINE;
6640 adev->card_status = CARD_STATUS_OFFLINE;
6641 ret = -EIO;
6642 goto exit;
6643 }
6644
Haynes Mathew George16081042017-05-31 17:16:49 -07006645 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6646 step = "open";
6647 ret = -ENODEV;
6648 goto exit;
6649 }
6650 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6651 if (ret < 0) {
6652 step = "begin";
6653 goto exit;
6654 }
juyuchen626833d2019-06-04 16:48:02 +08006655
6656 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006657 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006658 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006659 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006660 ret = platform_get_mmap_data_fd(adev->platform,
6661 out->pcm_device_id, 0 /*playback*/,
6662 &info->shared_memory_fd,
6663 &mmap_size);
6664 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006665 // Fall back to non exclusive mode
6666 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6667 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006668 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6669 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6670
Arun Mirpuri5d170872019-03-26 13:21:31 -07006671 if (mmap_size < buffer_size) {
6672 step = "mmap";
6673 goto exit;
6674 }
juyuchen626833d2019-06-04 16:48:02 +08006675 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006676 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006677 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006678 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006679
6680 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6681 if (ret < 0) {
6682 step = "commit";
6683 goto exit;
6684 }
6685
Phil Burkfe17efd2019-03-25 10:23:35 -07006686 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6687
Haynes Mathew George16081042017-05-31 17:16:49 -07006688 out->standby = false;
6689 ret = 0;
6690
Arun Mirpuri5d170872019-03-26 13:21:31 -07006691 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006692 __func__, info->shared_memory_address, info->buffer_size_frames);
6693
6694exit:
6695 if (ret != 0) {
6696 if (out->pcm == NULL) {
6697 ALOGE("%s: %s - %d", __func__, step, ret);
6698 } else {
6699 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6700 pcm_close(out->pcm);
6701 out->pcm = NULL;
6702 }
6703 }
6704 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306705 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006706 return ret;
6707}
6708
6709static int out_get_mmap_position(const struct audio_stream_out *stream,
6710 struct audio_mmap_position *position)
6711{
6712 struct stream_out *out = (struct stream_out *)stream;
6713 ALOGVV("%s", __func__);
6714 if (position == NULL) {
6715 return -EINVAL;
6716 }
6717 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006718 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006719 return -ENOSYS;
6720 }
6721 if (out->pcm == NULL) {
6722 return -ENOSYS;
6723 }
6724
6725 struct timespec ts = { 0, 0 };
6726 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6727 if (ret < 0) {
6728 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6729 return ret;
6730 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006731 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6732 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006733 return 0;
6734}
6735
6736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006737/** audio_stream_in implementation **/
6738static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6739{
6740 struct stream_in *in = (struct stream_in *)stream;
6741
6742 return in->config.rate;
6743}
6744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006745static int in_set_sample_rate(struct audio_stream *stream __unused,
6746 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006747{
6748 return -ENOSYS;
6749}
6750
6751static size_t in_get_buffer_size(const struct audio_stream *stream)
6752{
6753 struct stream_in *in = (struct stream_in *)stream;
6754
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006755 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6756 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006757 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6758 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306759 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306760 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006761
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006762 return in->config.period_size * in->af_period_multiplier *
6763 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006764}
6765
6766static uint32_t in_get_channels(const struct audio_stream *stream)
6767{
6768 struct stream_in *in = (struct stream_in *)stream;
6769
6770 return in->channel_mask;
6771}
6772
6773static audio_format_t in_get_format(const struct audio_stream *stream)
6774{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006775 struct stream_in *in = (struct stream_in *)stream;
6776
6777 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006778}
6779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006780static int in_set_format(struct audio_stream *stream __unused,
6781 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006782{
6783 return -ENOSYS;
6784}
6785
6786static int in_standby(struct audio_stream *stream)
6787{
6788 struct stream_in *in = (struct stream_in *)stream;
6789 struct audio_device *adev = in->dev;
6790 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306791 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6792 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006793 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306794
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006795 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006796 if (!in->standby && in->is_st_session) {
6797 ALOGD("%s: sound trigger pcm stop lab", __func__);
6798 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006799 if (adev->num_va_sessions > 0)
6800 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006801 in->standby = 1;
6802 }
6803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006804 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006805 if (adev->adm_deregister_stream)
6806 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6807
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006808 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006809 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006810 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006811 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006812 voice_extn_compress_voip_close_input_stream(stream);
6813 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006814 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6815 do_stop = in->capture_started;
6816 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006817 if (in->mmap_shared_memory_fd >= 0) {
6818 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6819 __func__, in->mmap_shared_memory_fd);
6820 close(in->mmap_shared_memory_fd);
6821 in->mmap_shared_memory_fd = -1;
6822 }
Zhou Songa8895042016-07-05 17:54:22 +08006823 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306824 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306825 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006826 }
6827
Arun Mirpuri5d170872019-03-26 13:21:31 -07006828 if (in->pcm) {
6829 ATRACE_BEGIN("pcm_in_close");
6830 pcm_close(in->pcm);
6831 ATRACE_END();
6832 in->pcm = NULL;
6833 }
6834
Carter Hsu2e429db2019-05-14 18:50:52 +08006835 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006836 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006837
George Gao3018ede2019-10-23 13:23:00 -07006838 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6839 if (adev->num_va_sessions > 0)
6840 adev->num_va_sessions--;
6841 }
Quinn Malef6050362019-01-30 15:55:40 -08006842
Eric Laurent150dbfe2013-02-27 14:31:02 -08006843 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844 }
6845 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006846 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006847 return status;
6848}
6849
Aalique Grahame22e49102018-12-18 14:23:57 -08006850static int in_dump(const struct audio_stream *stream,
6851 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852{
Aalique Grahame22e49102018-12-18 14:23:57 -08006853 struct stream_in *in = (struct stream_in *)stream;
6854
6855 // We try to get the lock for consistency,
6856 // but it isn't necessary for these variables.
6857 // If we're not in standby, we may be blocked on a read.
6858 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6859 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6860 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6861 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6862
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006863 char buffer[256]; // for statistics formatting
6864 if (in->start_latency_ms.n > 0) {
6865 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6866 dprintf(fd, " Start latency ms: %s\n", buffer);
6867 }
6868
Aalique Grahame22e49102018-12-18 14:23:57 -08006869 if (locked) {
6870 pthread_mutex_unlock(&in->lock);
6871 }
6872
6873 // dump error info
6874 (void)error_log_dump(
6875 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877 return 0;
6878}
6879
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306880static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6881{
6882 if (!stream || !parms)
6883 return;
6884
6885 struct stream_in *in = (struct stream_in *)stream;
6886 struct audio_device *adev = in->dev;
6887
6888 card_status_t status;
6889 int card;
6890 if (parse_snd_card_status(parms, &card, &status) < 0)
6891 return;
6892
6893 pthread_mutex_lock(&adev->lock);
6894 bool valid_cb = (card == adev->snd_card);
6895 pthread_mutex_unlock(&adev->lock);
6896
6897 if (!valid_cb)
6898 return;
6899
6900 lock_input_stream(in);
6901 if (in->card_status != status)
6902 in->card_status = status;
6903 pthread_mutex_unlock(&in->lock);
6904
6905 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6906 use_case_table[in->usecase],
6907 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6908
6909 // a better solution would be to report error back to AF and let
6910 // it put the stream to standby
6911 if (status == CARD_STATUS_OFFLINE)
6912 in_standby(&in->stream.common);
6913
6914 return;
6915}
6916
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006917int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006918 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006919 audio_source_t source)
6920{
6921 struct audio_device *adev = in->dev;
6922 int ret = 0;
6923
6924 lock_input_stream(in);
6925 pthread_mutex_lock(&adev->lock);
6926
6927 /* no audio source uses val == 0 */
6928 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6929 in->source = source;
6930 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6931 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6932 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6933 (in->config.rate == 8000 || in->config.rate == 16000 ||
6934 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6935 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6936 ret = voice_extn_compress_voip_open_input_stream(in);
6937 if (ret != 0) {
6938 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6939 __func__, ret);
6940 }
6941 }
6942 }
6943
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006944 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6945 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006946 // Workaround: If routing to an non existing usb device, fail gracefully
6947 // The routing request will otherwise block during 10 second
6948 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006949 struct str_parms *usb_addr =
6950 str_parms_create_str(get_usb_device_address(devices));
6951 if (is_usb_in_device_type(devices) && usb_addr &&
6952 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006953 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6954 ret = -ENOSYS;
6955 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006956 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006957 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006958 if (!in->standby && !in->is_st_session) {
6959 ALOGV("update input routing change");
6960 // inform adm before actual routing to prevent glitches.
6961 if (adev->adm_on_routing_change) {
6962 adev->adm_on_routing_change(adev->adm_data,
6963 in->capture_handle);
6964 ret = select_devices(adev, in->usecase);
6965 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6966 adev->adm_routing_changed = true;
6967 }
6968 }
6969 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006970 if (usb_addr)
6971 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006972 }
6973 pthread_mutex_unlock(&adev->lock);
6974 pthread_mutex_unlock(&in->lock);
6975
6976 ALOGD("%s: exit: status(%d)", __func__, ret);
6977 return ret;
6978}
6979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6981{
6982 struct stream_in *in = (struct stream_in *)stream;
6983 struct audio_device *adev = in->dev;
6984 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006985 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306986 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006987
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306988 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006989 parms = str_parms_create_str(kvpairs);
6990
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306991 if (!parms)
6992 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006993 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006994 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006995
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306996 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6997 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306998 strlcpy(in->profile, value, sizeof(in->profile));
6999 ALOGV("updating stream profile with value '%s'", in->profile);
7000 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
7001 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007002 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307003 in->sample_rate, in->bit_width,
7004 in->profile, &in->app_type_cfg);
7005 }
7006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007007 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08007008 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009
7010 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307011error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307012 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007013}
7014
7015static char* in_get_parameters(const struct audio_stream *stream,
7016 const char *keys)
7017{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007018 struct stream_in *in = (struct stream_in *)stream;
7019 struct str_parms *query = str_parms_create_str(keys);
7020 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007021 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007022
7023 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007024 if (reply) {
7025 str_parms_destroy(reply);
7026 }
7027 if (query) {
7028 str_parms_destroy(query);
7029 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007030 ALOGE("in_get_parameters: failed to create query or reply");
7031 return NULL;
7032 }
7033
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007034 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007035
7036 voice_extn_in_get_parameters(in, query, reply);
7037
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007038 stream_get_parameter_channels(query, reply,
7039 &in->supported_channel_masks[0]);
7040 stream_get_parameter_formats(query, reply,
7041 &in->supported_formats[0]);
7042 stream_get_parameter_rates(query, reply,
7043 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007044 str = str_parms_to_str(reply);
7045 str_parms_destroy(query);
7046 str_parms_destroy(reply);
7047
7048 ALOGV("%s: exit: returns - %s", __func__, str);
7049 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050}
7051
Aalique Grahame22e49102018-12-18 14:23:57 -08007052static int in_set_gain(struct audio_stream_in *stream,
7053 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007054{
Aalique Grahame22e49102018-12-18 14:23:57 -08007055 struct stream_in *in = (struct stream_in *)stream;
7056 char mixer_ctl_name[128];
7057 struct mixer_ctl *ctl;
7058 int ctl_value;
7059
7060 ALOGV("%s: gain %f", __func__, gain);
7061
7062 if (stream == NULL)
7063 return -EINVAL;
7064
7065 /* in_set_gain() only used to silence MMAP capture for now */
7066 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7067 return -ENOSYS;
7068
7069 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7070
7071 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7072 if (!ctl) {
7073 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7074 __func__, mixer_ctl_name);
7075 return -ENOSYS;
7076 }
7077
7078 if (gain < RECORD_GAIN_MIN)
7079 gain = RECORD_GAIN_MIN;
7080 else if (gain > RECORD_GAIN_MAX)
7081 gain = RECORD_GAIN_MAX;
7082 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7083
7084 mixer_ctl_set_value(ctl, 0, ctl_value);
7085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007086 return 0;
7087}
7088
7089static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7090 size_t bytes)
7091{
7092 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307093
7094 if (in == NULL) {
7095 ALOGE("%s: stream_in ptr is NULL", __func__);
7096 return -EINVAL;
7097 }
7098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007099 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307100 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307101 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007102
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007103 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307104
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007105 if (in->is_st_session) {
7106 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7107 /* Read from sound trigger HAL */
7108 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007109 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007110 if (adev->num_va_sessions < UINT_MAX)
7111 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007112 in->standby = 0;
7113 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007114 pthread_mutex_unlock(&in->lock);
7115 return bytes;
7116 }
7117
Haynes Mathew George16081042017-05-31 17:16:49 -07007118 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7119 ret = -ENOSYS;
7120 goto exit;
7121 }
7122
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007123 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7124 !in->standby && adev->adm_routing_changed) {
7125 ret = -ENOSYS;
7126 goto exit;
7127 }
7128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007129 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007130 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7131
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007132 pthread_mutex_lock(&adev->lock);
7133 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7134 ret = voice_extn_compress_voip_start_input_stream(in);
7135 else
7136 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007137 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7138 if (adev->num_va_sessions < UINT_MAX)
7139 adev->num_va_sessions++;
7140 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007141 pthread_mutex_unlock(&adev->lock);
7142 if (ret != 0) {
7143 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007144 }
7145 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007146
7147 // log startup time in ms.
7148 simple_stats_log(
7149 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007151
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307152 /* Avoid read if capture_stopped is set */
7153 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7154 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7155 ret = -EINVAL;
7156 goto exit;
7157 }
7158
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007159 // what's the duration requested by the client?
7160 long ns = 0;
7161
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307162 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007163 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7164 in->config.rate;
7165
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007166 ret = request_in_focus(in, ns);
7167 if (ret != 0)
7168 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007169 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007170
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307171 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307172 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7173 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307174 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007175 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307176 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007177 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007178 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007179 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007180 } else if (audio_extn_ffv_get_stream() == in) {
7181 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307182 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007183 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307184 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7185 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7186 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7187 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307188 ret = -EINVAL;
7189 goto exit;
7190 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307191 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307192 ret = -errno;
7193 }
7194 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307195 /* bytes read is always set to bytes for non compress usecases */
7196 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007197 }
7198
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007199 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007201 /*
Quinn Malef6050362019-01-30 15:55:40 -08007202 * Instead of writing zeroes here, we could trust the hardware to always
7203 * provide zeroes when muted. This is also muted with voice recognition
7204 * usecases so that other clients do not have access to voice recognition
7205 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007206 */
Quinn Malef6050362019-01-30 15:55:40 -08007207 if ((ret == 0 && voice_get_mic_mute(adev) &&
7208 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007209 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7210 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007211 (adev->num_va_sessions &&
7212 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7213 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7214 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007215 memset(buffer, 0, bytes);
7216
7217exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307218 frame_size = audio_stream_in_frame_size(stream);
7219 if (frame_size > 0)
7220 in->frames_read += bytes_read/frame_size;
7221
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007222 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307223 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 pthread_mutex_unlock(&in->lock);
7225
7226 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307227 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307228 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307229 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307230 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307231 in->standby = true;
7232 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307233 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307234 bytes_read = bytes;
7235 memset(buffer, 0, bytes);
7236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007237 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007238 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7239 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007240 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307241 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307242 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007243 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307244 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245}
7246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007247static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007248{
7249 return 0;
7250}
7251
Aalique Grahame22e49102018-12-18 14:23:57 -08007252static int in_get_capture_position(const struct audio_stream_in *stream,
7253 int64_t *frames, int64_t *time)
7254{
7255 if (stream == NULL || frames == NULL || time == NULL) {
7256 return -EINVAL;
7257 }
7258 struct stream_in *in = (struct stream_in *)stream;
7259 int ret = -ENOSYS;
7260
7261 lock_input_stream(in);
7262 // note: ST sessions do not close the alsa pcm driver synchronously
7263 // on standby. Therefore, we may return an error even though the
7264 // pcm stream is still opened.
7265 if (in->standby) {
7266 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7267 "%s stream in standby but pcm not NULL for non ST session", __func__);
7268 goto exit;
7269 }
7270 if (in->pcm) {
7271 struct timespec timestamp;
7272 unsigned int avail;
7273 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7274 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007275 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007276 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007277 ret = 0;
7278 }
7279 }
7280exit:
7281 pthread_mutex_unlock(&in->lock);
7282 return ret;
7283}
7284
Carter Hsu2e429db2019-05-14 18:50:52 +08007285static int in_update_effect_list(bool add, effect_handle_t effect,
7286 struct listnode *head)
7287{
7288 struct listnode *node;
7289 struct in_effect_list *elist = NULL;
7290 struct in_effect_list *target = NULL;
7291 int ret = 0;
7292
7293 if (!head)
7294 return ret;
7295
7296 list_for_each(node, head) {
7297 elist = node_to_item(node, struct in_effect_list, list);
7298 if (elist->handle == effect) {
7299 target = elist;
7300 break;
7301 }
7302 }
7303
7304 if (add) {
7305 if (target) {
7306 ALOGD("effect %p already exist", effect);
7307 return ret;
7308 }
7309
7310 target = (struct in_effect_list *)
7311 calloc(1, sizeof(struct in_effect_list));
7312
7313 if (!target) {
7314 ALOGE("%s:fail to allocate memory", __func__);
7315 return -ENOMEM;
7316 }
7317
7318 target->handle = effect;
7319 list_add_tail(head, &target->list);
7320 } else {
7321 if (target) {
7322 list_remove(&target->list);
7323 free(target);
7324 }
7325 }
7326
7327 return ret;
7328}
7329
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007330static int add_remove_audio_effect(const struct audio_stream *stream,
7331 effect_handle_t effect,
7332 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007334 struct stream_in *in = (struct stream_in *)stream;
7335 int status = 0;
7336 effect_descriptor_t desc;
7337
7338 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007339 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7340
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007341 if (status != 0)
7342 return status;
7343
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007344 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007345 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007346 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007347 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7348 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007349 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007350
7351 in_update_effect_list(enable, effect, &in->aec_list);
7352 enable = !list_empty(&in->aec_list);
7353 if (enable == in->enable_aec)
7354 goto exit;
7355
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007356 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007357 ALOGD("AEC enable %d", enable);
7358
Aalique Grahame22e49102018-12-18 14:23:57 -08007359 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7360 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7361 in->dev->enable_voicerx = enable;
7362 struct audio_usecase *usecase;
7363 struct listnode *node;
7364 list_for_each(node, &in->dev->usecase_list) {
7365 usecase = node_to_item(node, struct audio_usecase, list);
7366 if (usecase->type == PCM_PLAYBACK)
7367 select_devices(in->dev, usecase->id);
7368 }
7369 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007370 if (!in->standby) {
7371 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7372 select_devices(in->dev, in->usecase);
7373 }
7374
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007375 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007376 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7377
7378 in_update_effect_list(enable, effect, &in->ns_list);
7379 enable = !list_empty(&in->ns_list);
7380 if (enable == in->enable_ns)
7381 goto exit;
7382
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007383 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007384 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007385 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007386 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7387 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007388 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7389 select_devices(in->dev, in->usecase);
7390 } else
7391 select_devices(in->dev, in->usecase);
7392 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007393 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007394exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007395 pthread_mutex_unlock(&in->dev->lock);
7396 pthread_mutex_unlock(&in->lock);
7397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007398 return 0;
7399}
7400
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007401static int in_add_audio_effect(const struct audio_stream *stream,
7402 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007403{
Eric Laurent994a6932013-07-17 11:51:42 -07007404 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007405 return add_remove_audio_effect(stream, effect, true);
7406}
7407
7408static int in_remove_audio_effect(const struct audio_stream *stream,
7409 effect_handle_t effect)
7410{
Eric Laurent994a6932013-07-17 11:51:42 -07007411 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007412 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007413}
7414
Derek Chenf939fb72018-11-13 13:34:41 -08007415streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7416 audio_io_handle_t input)
7417{
7418 struct listnode *node;
7419
7420 list_for_each(node, &dev->active_inputs_list) {
7421 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7422 streams_input_ctxt_t,
7423 list);
7424 if (in_ctxt->input->capture_handle == input) {
7425 return in_ctxt;
7426 }
7427 }
7428 return NULL;
7429}
7430
7431streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7432 audio_io_handle_t output)
7433{
7434 struct listnode *node;
7435
7436 list_for_each(node, &dev->active_outputs_list) {
7437 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7438 streams_output_ctxt_t,
7439 list);
7440 if (out_ctxt->output->handle == output) {
7441 return out_ctxt;
7442 }
7443 }
7444 return NULL;
7445}
7446
Haynes Mathew George16081042017-05-31 17:16:49 -07007447static int in_stop(const struct audio_stream_in* stream)
7448{
7449 struct stream_in *in = (struct stream_in *)stream;
7450 struct audio_device *adev = in->dev;
7451
7452 int ret = -ENOSYS;
7453 ALOGV("%s", __func__);
7454 pthread_mutex_lock(&adev->lock);
7455 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7456 in->capture_started && in->pcm != NULL) {
7457 pcm_stop(in->pcm);
7458 ret = stop_input_stream(in);
7459 in->capture_started = false;
7460 }
7461 pthread_mutex_unlock(&adev->lock);
7462 return ret;
7463}
7464
7465static int in_start(const struct audio_stream_in* stream)
7466{
7467 struct stream_in *in = (struct stream_in *)stream;
7468 struct audio_device *adev = in->dev;
7469 int ret = -ENOSYS;
7470
7471 ALOGV("%s in %p", __func__, in);
7472 pthread_mutex_lock(&adev->lock);
7473 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7474 !in->capture_started && in->pcm != NULL) {
7475 if (!in->capture_started) {
7476 ret = start_input_stream(in);
7477 if (ret == 0) {
7478 in->capture_started = true;
7479 }
7480 }
7481 }
7482 pthread_mutex_unlock(&adev->lock);
7483 return ret;
7484}
7485
Phil Burke0a86d12019-02-16 22:28:11 -08007486// Read offset for the positional timestamp from a persistent vendor property.
7487// This is to workaround apparent inaccuracies in the timing information that
7488// is used by the AAudio timing model. The inaccuracies can cause glitches.
7489static int64_t in_get_mmap_time_offset() {
7490 const int32_t kDefaultOffsetMicros = 0;
7491 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007492 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007493 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7494 return mmap_time_offset_micros * (int64_t)1000;
7495}
7496
Haynes Mathew George16081042017-05-31 17:16:49 -07007497static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7498 int32_t min_size_frames,
7499 struct audio_mmap_buffer_info *info)
7500{
7501 struct stream_in *in = (struct stream_in *)stream;
7502 struct audio_device *adev = in->dev;
7503 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007504 unsigned int offset1 = 0;
7505 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007506 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007507 uint32_t mmap_size = 0;
7508 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007509
7510 pthread_mutex_lock(&adev->lock);
7511 ALOGV("%s in %p", __func__, in);
7512
Sharad Sanglec6f32552018-05-04 16:15:38 +05307513 if (CARD_STATUS_OFFLINE == in->card_status||
7514 CARD_STATUS_OFFLINE == adev->card_status) {
7515 ALOGW("in->card_status or adev->card_status offline, try again");
7516 ret = -EIO;
7517 goto exit;
7518 }
7519
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307520 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007521 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7522 ret = -EINVAL;
7523 goto exit;
7524 }
7525 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7526 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7527 ALOGV("%s in %p", __func__, in);
7528 ret = -ENOSYS;
7529 goto exit;
7530 }
7531 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7532 if (in->pcm_device_id < 0) {
7533 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7534 __func__, in->pcm_device_id, in->usecase);
7535 ret = -EINVAL;
7536 goto exit;
7537 }
7538
7539 adjust_mmap_period_count(&in->config, min_size_frames);
7540
7541 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7542 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7543 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7544 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307545 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307546 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7547 in->card_status = CARD_STATUS_OFFLINE;
7548 adev->card_status = CARD_STATUS_OFFLINE;
7549 ret = -EIO;
7550 goto exit;
7551 }
7552
Haynes Mathew George16081042017-05-31 17:16:49 -07007553 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7554 step = "open";
7555 ret = -ENODEV;
7556 goto exit;
7557 }
7558
7559 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7560 if (ret < 0) {
7561 step = "begin";
7562 goto exit;
7563 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007564
juyuchen626833d2019-06-04 16:48:02 +08007565 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007566 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7567 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7568 info->burst_size_frames = in->config.period_size;
7569 ret = platform_get_mmap_data_fd(adev->platform,
7570 in->pcm_device_id, 1 /*capture*/,
7571 &info->shared_memory_fd,
7572 &mmap_size);
7573 if (ret < 0) {
7574 // Fall back to non exclusive mode
7575 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7576 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007577 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7578 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7579
Arun Mirpuri5d170872019-03-26 13:21:31 -07007580 if (mmap_size < buffer_size) {
7581 step = "mmap";
7582 goto exit;
7583 }
juyuchen626833d2019-06-04 16:48:02 +08007584 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007585 }
7586
7587 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007588
7589 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7590 if (ret < 0) {
7591 step = "commit";
7592 goto exit;
7593 }
7594
Phil Burke0a86d12019-02-16 22:28:11 -08007595 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7596
Haynes Mathew George16081042017-05-31 17:16:49 -07007597 in->standby = false;
7598 ret = 0;
7599
7600 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7601 __func__, info->shared_memory_address, info->buffer_size_frames);
7602
7603exit:
7604 if (ret != 0) {
7605 if (in->pcm == NULL) {
7606 ALOGE("%s: %s - %d", __func__, step, ret);
7607 } else {
7608 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7609 pcm_close(in->pcm);
7610 in->pcm = NULL;
7611 }
7612 }
7613 pthread_mutex_unlock(&adev->lock);
7614 return ret;
7615}
7616
7617static int in_get_mmap_position(const struct audio_stream_in *stream,
7618 struct audio_mmap_position *position)
7619{
7620 struct stream_in *in = (struct stream_in *)stream;
7621 ALOGVV("%s", __func__);
7622 if (position == NULL) {
7623 return -EINVAL;
7624 }
7625 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7626 return -ENOSYS;
7627 }
7628 if (in->pcm == NULL) {
7629 return -ENOSYS;
7630 }
7631 struct timespec ts = { 0, 0 };
7632 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7633 if (ret < 0) {
7634 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7635 return ret;
7636 }
Phil Burke0a86d12019-02-16 22:28:11 -08007637 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7638 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007639 return 0;
7640}
7641
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307642static int in_get_active_microphones(const struct audio_stream_in *stream,
7643 struct audio_microphone_characteristic_t *mic_array,
7644 size_t *mic_count) {
7645 struct stream_in *in = (struct stream_in *)stream;
7646 struct audio_device *adev = in->dev;
7647 ALOGVV("%s", __func__);
7648
7649 lock_input_stream(in);
7650 pthread_mutex_lock(&adev->lock);
7651 int ret = platform_get_active_microphones(adev->platform,
7652 audio_channel_count_from_in_mask(in->channel_mask),
7653 in->usecase, mic_array, mic_count);
7654 pthread_mutex_unlock(&adev->lock);
7655 pthread_mutex_unlock(&in->lock);
7656
7657 return ret;
7658}
7659
7660static int adev_get_microphones(const struct audio_hw_device *dev,
7661 struct audio_microphone_characteristic_t *mic_array,
7662 size_t *mic_count) {
7663 struct audio_device *adev = (struct audio_device *)dev;
7664 ALOGVV("%s", __func__);
7665
7666 pthread_mutex_lock(&adev->lock);
7667 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7668 pthread_mutex_unlock(&adev->lock);
7669
7670 return ret;
7671}
juyuchendb308c22019-01-21 11:57:17 -07007672
7673static void in_update_sink_metadata(struct audio_stream_in *stream,
7674 const struct sink_metadata *sink_metadata) {
7675
7676 if (stream == NULL
7677 || sink_metadata == NULL
7678 || sink_metadata->tracks == NULL) {
7679 return;
7680 }
7681
7682 int error = 0;
7683 struct stream_in *in = (struct stream_in *)stream;
7684 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007685 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007686 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007687
7688 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007689
7690 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007691 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007692
7693 lock_input_stream(in);
7694 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007695 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007696
Zhou Song62ea0282020-03-22 19:53:01 +08007697 is_ha_usecase = adev->ha_proxy_enable ?
7698 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7699 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7700 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007701 && adev->voice_tx_output != NULL) {
7702 /* Use the rx device from afe-proxy record to route voice call because
7703 there is no routing if tx device is on primary hal and rx device
7704 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007705 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007706
7707 if (!voice_is_call_state_active(adev)) {
7708 if (adev->mode == AUDIO_MODE_IN_CALL) {
7709 adev->current_call_output = adev->voice_tx_output;
7710 error = voice_start_call(adev);
7711 if (error != 0)
7712 ALOGE("%s: start voice call failed %d", __func__, error);
7713 }
7714 } else {
7715 adev->current_call_output = adev->voice_tx_output;
7716 voice_update_devices_for_all_voice_usecases(adev);
7717 }
7718 }
7719
7720 pthread_mutex_unlock(&adev->lock);
7721 pthread_mutex_unlock(&in->lock);
7722}
7723
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307724int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007725 audio_io_handle_t handle,
7726 audio_devices_t devices,
7727 audio_output_flags_t flags,
7728 struct audio_config *config,
7729 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007730 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007731{
7732 struct audio_device *adev = (struct audio_device *)dev;
7733 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307734 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007735 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007736 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307737 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007738 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7739 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7740 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7741 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007742 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007743 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7744 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007745 bool force_haptic_path =
7746 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007747 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007748#ifdef AUDIO_GKI_ENABLED
7749 __s32 *generic_dec;
7750#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007751
kunleizdff872d2018-08-20 14:40:33 +08007752 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007753 is_usb_dev = false;
7754 devices = AUDIO_DEVICE_OUT_SPEAKER;
7755 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7756 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007757 if (config->format == AUDIO_FORMAT_DEFAULT)
7758 config->format = AUDIO_FORMAT_PCM_16_BIT;
7759 if (config->sample_rate == 0)
7760 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7761 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7762 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007763 }
7764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007765 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307766
Rahul Sharma99770982019-03-06 17:05:26 +05307767 pthread_mutex_lock(&adev->lock);
7768 if (out_get_stream(adev, handle) != NULL) {
7769 ALOGW("%s, output stream already opened", __func__);
7770 ret = -EEXIST;
7771 }
7772 pthread_mutex_unlock(&adev->lock);
7773 if (ret)
7774 return ret;
7775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007776 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7777
Mingming Yin3a941d42016-02-17 18:08:05 -08007778 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007779 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7780 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307781
7782
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007783 if (!out) {
7784 return -ENOMEM;
7785 }
7786
Haynes Mathew George204045b2015-02-25 20:32:03 -08007787 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007788 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007789 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007790 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007791 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007793 if (devices == AUDIO_DEVICE_NONE)
7794 devices = AUDIO_DEVICE_OUT_SPEAKER;
7795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007796 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007797 list_init(&out->device_list);
7798 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007799 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007800 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007801 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307802 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307803 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7804 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7805 else
7806 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007807 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007808 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007809 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307810 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307811 out->started = 0;
Zhou Song1f93fa52020-11-20 13:57:39 +08007812 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007813 out->hal_output_suspend_supported = 0;
7814 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307815 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307816 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307817 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007818 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007819
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307820 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307821 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007822 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7823
Aalique Grahame22e49102018-12-18 14:23:57 -08007824 if (direct_dev &&
7825 (audio_is_linear_pcm(out->format) ||
7826 config->format == AUDIO_FORMAT_DEFAULT) &&
7827 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7828 audio_format_t req_format = config->format;
7829 audio_channel_mask_t req_channel_mask = config->channel_mask;
7830 uint32_t req_sample_rate = config->sample_rate;
7831
7832 pthread_mutex_lock(&adev->lock);
7833 if (is_hdmi) {
7834 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7835 ret = read_hdmi_sink_caps(out);
7836 if (config->sample_rate == 0)
7837 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7838 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7839 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7840 if (config->format == AUDIO_FORMAT_DEFAULT)
7841 config->format = AUDIO_FORMAT_PCM_16_BIT;
7842 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007843 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7844 &config->format,
7845 &out->supported_formats[0],
7846 MAX_SUPPORTED_FORMATS,
7847 &config->channel_mask,
7848 &out->supported_channel_masks[0],
7849 MAX_SUPPORTED_CHANNEL_MASKS,
7850 &config->sample_rate,
7851 &out->supported_sample_rates[0],
7852 MAX_SUPPORTED_SAMPLE_RATES);
7853 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007854 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007855
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007856 pthread_mutex_unlock(&adev->lock);
7857 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007858 if (ret == -ENOSYS) {
7859 /* ignore and go with default */
7860 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007861 }
7862 // For MMAP NO IRQ, allow conversions in ADSP
7863 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7864 goto error_open;
7865 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007866 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007867 goto error_open;
7868 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007869
7870 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7871 config->sample_rate = req_sample_rate;
7872 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7873 config->channel_mask = req_channel_mask;
7874 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7875 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007876 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007877
7878 out->sample_rate = config->sample_rate;
7879 out->channel_mask = config->channel_mask;
7880 out->format = config->format;
7881 if (is_hdmi) {
7882 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7883 out->config = pcm_config_hdmi_multi;
7884 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7885 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7886 out->config = pcm_config_mmap_playback;
7887 out->stream.start = out_start;
7888 out->stream.stop = out_stop;
7889 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7890 out->stream.get_mmap_position = out_get_mmap_position;
7891 } else {
7892 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7893 out->config = pcm_config_hifi;
7894 }
7895
7896 out->config.rate = out->sample_rate;
7897 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7898 if (is_hdmi) {
7899 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7900 audio_bytes_per_sample(out->format));
7901 }
7902 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007903 }
7904
Derek Chenf6318be2017-06-12 17:16:24 -04007905 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007906 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007907 /* extract car audio stream index */
7908 out->car_audio_stream =
7909 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7910 if (out->car_audio_stream < 0) {
7911 ALOGE("%s: invalid car audio stream %x",
7912 __func__, out->car_audio_stream);
7913 ret = -EINVAL;
7914 goto error_open;
7915 }
Derek Chen5f67a942020-02-24 23:08:13 -08007916 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007917 }
7918
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007919 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007920 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007921 if (!voice_extn_is_compress_voip_supported()) {
7922 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7923 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007924 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307925 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007926 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7927 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007928 out->volume_l = INVALID_OUT_VOLUME;
7929 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007930
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007931 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007932 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007933 uint32_t channel_count =
7934 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307935 out->config.channels = channel_count;
7936
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007937 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7938 out->sample_rate, out->format,
7939 channel_count, false);
7940 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7941 if (frame_size != 0)
7942 out->config.period_size = buffer_size / frame_size;
7943 else
7944 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007945 }
7946 } else {
7947 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7948 voice_extn_compress_voip_is_active(out->dev)) &&
7949 (voice_extn_compress_voip_is_config_supported(config))) {
7950 ret = voice_extn_compress_voip_open_output_stream(out);
7951 if (ret != 0) {
7952 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7953 __func__, ret);
7954 goto error_open;
7955 }
Sujin Panicker19027262019-09-16 18:28:06 +05307956 } else {
7957 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7958 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007959 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007960 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007961 } else if (audio_is_linear_pcm(out->format) &&
7962 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7963 out->channel_mask = config->channel_mask;
7964 out->sample_rate = config->sample_rate;
7965 out->format = config->format;
7966 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7967 // does this change?
7968 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7969 out->config.rate = config->sample_rate;
7970 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7971 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7972 audio_bytes_per_sample(config->format));
7973 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007974 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307975 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307976 pthread_mutex_lock(&adev->lock);
7977 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7978 pthread_mutex_unlock(&adev->lock);
7979
7980 // reject offload during card offline to allow
7981 // fallback to s/w paths
7982 if (offline) {
7983 ret = -ENODEV;
7984 goto error_open;
7985 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007986
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007987 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7988 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7989 ALOGE("%s: Unsupported Offload information", __func__);
7990 ret = -EINVAL;
7991 goto error_open;
7992 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007993
Atul Khare3fa6e542017-08-09 00:56:17 +05307994 if (config->offload_info.format == 0)
7995 config->offload_info.format = config->format;
7996 if (config->offload_info.sample_rate == 0)
7997 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007998
Mingming Yin90310102013-11-13 16:57:00 -08007999 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308000 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07008001 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008002 ret = -EINVAL;
8003 goto error_open;
8004 }
8005
Ben Romberger0f8c87b2017-05-24 17:41:11 -07008006 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
8007 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
8008 (audio_extn_passthru_is_passthrough_stream(out)) &&
8009 !((config->sample_rate == 48000) ||
8010 (config->sample_rate == 96000) ||
8011 (config->sample_rate == 192000))) {
8012 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8013 __func__, config->sample_rate, config->offload_info.format);
8014 ret = -EINVAL;
8015 goto error_open;
8016 }
8017
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008018 out->compr_config.codec = (struct snd_codec *)
8019 calloc(1, sizeof(struct snd_codec));
8020
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008021 if (!out->compr_config.codec) {
8022 ret = -ENOMEM;
8023 goto error_open;
8024 }
8025
Dhananjay Kumarac341582017-02-23 23:42:25 +05308026 out->stream.pause = out_pause;
8027 out->stream.resume = out_resume;
8028 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308029 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308030 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008031 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308032 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008033 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308034 } else {
8035 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8036 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008037 }
vivek mehta446c3962015-09-14 10:57:35 -07008038
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308039 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8040 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008041#ifdef AUDIO_GKI_ENABLED
8042 /* out->compr_config.codec->reserved[1] is for flags */
8043 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8044#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308045 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008046#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308047 }
8048
vivek mehta446c3962015-09-14 10:57:35 -07008049 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008050 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008051 config->format == 0 && config->sample_rate == 0 &&
8052 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008053 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008054 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8055 } else {
8056 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8057 ret = -EEXIST;
8058 goto error_open;
8059 }
vivek mehta446c3962015-09-14 10:57:35 -07008060 }
8061
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008062 if (config->offload_info.channel_mask)
8063 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008064 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008065 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008066 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008067 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308068 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008069 ret = -EINVAL;
8070 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008071 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008072
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008073 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008074 out->sample_rate = config->offload_info.sample_rate;
8075
Mingming Yin3ee55c62014-08-04 14:23:35 -07008076 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008077
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308078 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308079 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308080 audio_extn_dolby_send_ddp_endp_params(adev);
8081 audio_extn_dolby_set_dmid(adev);
8082 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008084 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008085 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008086 out->compr_config.codec->bit_rate =
8087 config->offload_info.bit_rate;
8088 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308089 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008090 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308091 /* Update bit width only for non passthrough usecases.
8092 * For passthrough usecases, the output will always be opened @16 bit
8093 */
8094 if (!audio_extn_passthru_is_passthrough_stream(out))
8095 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308096
8097 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008098#ifdef AUDIO_GKI_ENABLED
8099 /* out->compr_config.codec->reserved[1] is for flags */
8100 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8101 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8102#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308103 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8104 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008105#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308106
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008107 /*TODO: Do we need to change it for passthrough */
8108 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008109
Manish Dewangana6fc5442015-08-24 20:30:31 +05308110 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8111 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308112 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308113 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308114 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8115 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308116
8117 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8118 AUDIO_FORMAT_PCM) {
8119
8120 /*Based on platform support, configure appropriate alsa format for corresponding
8121 *hal input format.
8122 */
8123 out->compr_config.codec->format = hal_format_to_alsa(
8124 config->offload_info.format);
8125
Ashish Jain83a6cc22016-06-28 14:34:17 +05308126 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308127 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308128 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308129
Dhananjay Kumarac341582017-02-23 23:42:25 +05308130 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308131 *hal input format and alsa format might differ based on platform support.
8132 */
8133 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308134 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308135
8136 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8137
Deeraj Soman93155a62019-09-30 19:00:37 +05308138 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8139 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8140 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8141 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8142 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308143
Ashish Jainf1eaa582016-05-23 20:54:24 +05308144 /* Check if alsa session is configured with the same format as HAL input format,
8145 * if not then derive correct fragment size needed to accomodate the
8146 * conversion of HAL input format to alsa format.
8147 */
8148 audio_extn_utils_update_direct_pcm_fragment_size(out);
8149
8150 /*if hal input and output fragment size is different this indicates HAL input format is
8151 *not same as the alsa format
8152 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308153 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308154 /*Allocate a buffer to convert input data to the alsa configured format.
8155 *size of convert buffer is equal to the size required to hold one fragment size
8156 *worth of pcm data, this is because flinger does not write more than fragment_size
8157 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308158 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8159 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308160 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8161 ret = -ENOMEM;
8162 goto error_open;
8163 }
8164 }
8165 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8166 out->compr_config.fragment_size =
8167 audio_extn_passthru_get_buffer_size(&config->offload_info);
8168 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8169 } else {
8170 out->compr_config.fragment_size =
8171 platform_get_compress_offload_buffer_size(&config->offload_info);
8172 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8173 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008174
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308175 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8176 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8177 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008178 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8179#ifdef AUDIO_GKI_ENABLED
8180 generic_dec =
8181 &(out->compr_config.codec->options.generic.reserved[1]);
8182 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8183 AUDIO_OUTPUT_BIT_WIDTH;
8184#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308185 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008186#endif
8187 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008188
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308189 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8190 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8191 }
8192
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008193 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8194 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008195
Manish Dewangan69426c82017-01-30 17:35:36 +05308196 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8197 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8198 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8199 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8200 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8201 } else {
8202 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8203 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008204
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308205 memset(&out->channel_map_param, 0,
8206 sizeof(struct audio_out_channel_map_param));
8207
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008208 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308209 out->send_next_track_params = false;
8210 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008211 out->offload_state = OFFLOAD_STATE_IDLE;
8212 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008213 out->writeAt.tv_sec = 0;
8214 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008215
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008216 audio_extn_dts_create_state_notifier_node(out->usecase);
8217
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008218 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8219 __func__, config->offload_info.version,
8220 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308221
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308222 /* Check if DSD audio format is supported in codec
8223 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308224 */
8225
8226 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308227 (!platform_check_codec_dsd_support(adev->platform) ||
8228 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308229 ret = -EINVAL;
8230 goto error_open;
8231 }
8232
Ashish Jain5106d362016-05-11 19:23:33 +05308233 /* Disable gapless if any of the following is true
8234 * passthrough playback
8235 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308236 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308237 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308238 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308239 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008240 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308241 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308242 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308243 check_and_set_gapless_mode(adev, false);
8244 } else
8245 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008246
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308247 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008248 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8249 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308250 if (config->format == AUDIO_FORMAT_DSD) {
8251 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008252#ifdef AUDIO_GKI_ENABLED
8253 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8254 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8255#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308256 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008257#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308258 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008259
8260 create_offload_callback_thread(out);
8261
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008262 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008263 switch (config->sample_rate) {
8264 case 0:
8265 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8266 break;
8267 case 8000:
8268 case 16000:
8269 case 48000:
8270 out->sample_rate = config->sample_rate;
8271 break;
8272 default:
8273 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8274 config->sample_rate);
8275 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8276 ret = -EINVAL;
8277 goto error_open;
8278 }
8279 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8280 switch (config->channel_mask) {
8281 case AUDIO_CHANNEL_NONE:
8282 case AUDIO_CHANNEL_OUT_STEREO:
8283 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8284 break;
8285 default:
8286 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8287 config->channel_mask);
8288 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8289 ret = -EINVAL;
8290 goto error_open;
8291 }
8292 switch (config->format) {
8293 case AUDIO_FORMAT_DEFAULT:
8294 case AUDIO_FORMAT_PCM_16_BIT:
8295 out->format = AUDIO_FORMAT_PCM_16_BIT;
8296 break;
8297 default:
8298 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8299 config->format);
8300 config->format = AUDIO_FORMAT_PCM_16_BIT;
8301 ret = -EINVAL;
8302 goto error_open;
8303 }
8304
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308305 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008306 if (ret != 0) {
8307 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008308 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008309 goto error_open;
8310 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008311 } else if (is_single_device_type_equal(&out->device_list,
8312 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008313 switch (config->sample_rate) {
8314 case 0:
8315 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8316 break;
8317 case 8000:
8318 case 16000:
8319 case 48000:
8320 out->sample_rate = config->sample_rate;
8321 break;
8322 default:
8323 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8324 config->sample_rate);
8325 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8326 ret = -EINVAL;
8327 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008328 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008329 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8330 switch (config->channel_mask) {
8331 case AUDIO_CHANNEL_NONE:
8332 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8333 break;
8334 case AUDIO_CHANNEL_OUT_STEREO:
8335 out->channel_mask = config->channel_mask;
8336 break;
8337 default:
8338 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8339 config->channel_mask);
8340 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8341 ret = -EINVAL;
8342 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008343 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008344 switch (config->format) {
8345 case AUDIO_FORMAT_DEFAULT:
8346 out->format = AUDIO_FORMAT_PCM_16_BIT;
8347 break;
8348 case AUDIO_FORMAT_PCM_16_BIT:
8349 out->format = config->format;
8350 break;
8351 default:
8352 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8353 config->format);
8354 config->format = AUDIO_FORMAT_PCM_16_BIT;
8355 ret = -EINVAL;
8356 break;
8357 }
8358 if (ret != 0)
8359 goto error_open;
8360
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008361 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8362 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008363 out->config.rate = out->sample_rate;
8364 out->config.channels =
8365 audio_channel_count_from_out_mask(out->channel_mask);
8366 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008367 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008368 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308369 unsigned int channels = 0;
8370 /*Update config params to default if not set by the caller*/
8371 if (config->sample_rate == 0)
8372 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8373 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8374 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8375 if (config->format == AUDIO_FORMAT_DEFAULT)
8376 config->format = AUDIO_FORMAT_PCM_16_BIT;
8377
8378 channels = audio_channel_count_from_out_mask(out->channel_mask);
8379
Varun Balaraje49253e2017-07-06 19:48:56 +05308380 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8381 out->usecase = get_interactive_usecase(adev);
8382 out->config = pcm_config_low_latency;
8383 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308384 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008385 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8386 out->flags);
8387 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008388 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8389 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8390 out->config = pcm_config_mmap_playback;
8391 out->stream.start = out_start;
8392 out->stream.stop = out_stop;
8393 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8394 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308395 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8396 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008397 out->hal_output_suspend_supported =
8398 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8399 out->dynamic_pm_qos_config_supported =
8400 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8401 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008402 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8403 } else {
8404 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8405 //the mixer path will be a string similar to "low-latency-playback resume"
8406 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8407 strlcat(out->pm_qos_mixer_path,
8408 " resume", MAX_MIXER_PATH_LEN);
8409 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8410 out->pm_qos_mixer_path);
8411 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308412 out->config = pcm_config_low_latency;
8413 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8414 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8415 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308416 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8417 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8418 if (out->config.period_size <= 0) {
8419 ALOGE("Invalid configuration period size is not valid");
8420 ret = -EINVAL;
8421 goto error_open;
8422 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008423 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8424 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8425 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008426 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8427 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8428 out->config = pcm_config_haptics_audio;
8429 if (force_haptic_path)
8430 adev->haptics_config = pcm_config_haptics_audio;
8431 else
8432 adev->haptics_config = pcm_config_haptics;
8433
Meng Wangd08ce322020-04-02 08:59:20 +08008434 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008435 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8436
8437 if (force_haptic_path) {
8438 out->config.channels = 1;
8439 adev->haptics_config.channels = 1;
8440 } else
8441 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 -08008442 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008443 ret = audio_extn_auto_hal_open_output_stream(out);
8444 if (ret) {
8445 ALOGE("%s: Failed to open output stream for bus device", __func__);
8446 ret = -EINVAL;
8447 goto error_open;
8448 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308449 } else {
8450 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008451 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8452 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308453 }
8454 out->hal_ip_format = format = out->format;
8455 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8456 out->hal_op_format = pcm_format_to_hal(out->config.format);
8457 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8458 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008459 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308460 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308461 if (out->hal_ip_format != out->hal_op_format) {
8462 uint32_t buffer_size = out->config.period_size *
8463 format_to_bitwidth_table[out->hal_op_format] *
8464 out->config.channels;
8465 out->convert_buffer = calloc(1, buffer_size);
8466 if (out->convert_buffer == NULL){
8467 ALOGE("Allocation failed for convert buffer for size %d",
8468 out->compr_config.fragment_size);
8469 ret = -ENOMEM;
8470 goto error_open;
8471 }
8472 ALOGD("Convert buffer allocated of size %d", buffer_size);
8473 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474 }
8475
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008476 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8477 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308478
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008479 /* TODO remove this hardcoding and check why width is zero*/
8480 if (out->bit_width == 0)
8481 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308482 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008483 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008484 &out->device_list, out->flags,
8485 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308486 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308487 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008488 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008489 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8490 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008491 if(adev->primary_output == NULL)
8492 adev->primary_output = out;
8493 else {
8494 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008495 ret = -EEXIST;
8496 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008497 }
8498 }
8499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008500 /* Check if this usecase is already existing */
8501 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008502 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8503 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008504 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008506 ret = -EEXIST;
8507 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008508 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008510 pthread_mutex_unlock(&adev->lock);
8511
8512 out->stream.common.get_sample_rate = out_get_sample_rate;
8513 out->stream.common.set_sample_rate = out_set_sample_rate;
8514 out->stream.common.get_buffer_size = out_get_buffer_size;
8515 out->stream.common.get_channels = out_get_channels;
8516 out->stream.common.get_format = out_get_format;
8517 out->stream.common.set_format = out_set_format;
8518 out->stream.common.standby = out_standby;
8519 out->stream.common.dump = out_dump;
8520 out->stream.common.set_parameters = out_set_parameters;
8521 out->stream.common.get_parameters = out_get_parameters;
8522 out->stream.common.add_audio_effect = out_add_audio_effect;
8523 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8524 out->stream.get_latency = out_get_latency;
8525 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008526#ifdef NO_AUDIO_OUT
8527 out->stream.write = out_write_for_no_output;
8528#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008530#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008531 out->stream.get_render_position = out_get_render_position;
8532 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008533 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534
Haynes Mathew George16081042017-05-31 17:16:49 -07008535 if (out->realtime)
8536 out->af_period_multiplier = af_period_multiplier;
8537 else
8538 out->af_period_multiplier = 1;
8539
Andy Hunga1f48fa2019-07-01 18:14:53 -07008540 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008542 out->standby = 1;
Zhou Song1f93fa52020-11-20 13:57:39 +08008543 out->volume_l = PLAYBACK_GAIN_MAX;
8544 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008545 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008546 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008547
8548 config->format = out->stream.common.get_format(&out->stream.common);
8549 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8550 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308551 register_format(out->format, out->supported_formats);
8552 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8553 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008554
Aalique Grahame22e49102018-12-18 14:23:57 -08008555 out->error_log = error_log_create(
8556 ERROR_LOG_ENTRIES,
8557 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8558
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308559 /*
8560 By locking output stream before registering, we allow the callback
8561 to update stream's state only after stream's initial state is set to
8562 adev state.
8563 */
8564 lock_output_stream(out);
8565 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8566 pthread_mutex_lock(&adev->lock);
8567 out->card_status = adev->card_status;
8568 pthread_mutex_unlock(&adev->lock);
8569 pthread_mutex_unlock(&out->lock);
8570
Aalique Grahame22e49102018-12-18 14:23:57 -08008571 stream_app_type_cfg_init(&out->app_type_cfg);
8572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008573 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308574 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008575 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008576
8577 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8578 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8579 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008580 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308581 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008582 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008583 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308584 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8585 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008586 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8587 out->usecase, PCM_PLAYBACK);
8588 hdlr_stream_cfg.flags = out->flags;
8589 hdlr_stream_cfg.type = PCM_PLAYBACK;
8590 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8591 &hdlr_stream_cfg);
8592 if (ret) {
8593 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8594 out->adsp_hdlr_stream_handle = NULL;
8595 }
8596 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308597 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8598 is_direct_passthough, false);
8599 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8600 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008601 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008602 if (ret < 0) {
8603 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8604 out->ip_hdlr_handle = NULL;
8605 }
8606 }
Derek Chenf939fb72018-11-13 13:34:41 -08008607
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008608 ret = io_streams_map_insert(adev, &out->stream.common,
8609 out->handle, AUDIO_PATCH_HANDLE_NONE);
8610 if (ret != 0)
8611 goto error_open;
8612
Derek Chenf939fb72018-11-13 13:34:41 -08008613 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8614 calloc(1, sizeof(streams_output_ctxt_t));
8615 if (out_ctxt == NULL) {
8616 ALOGE("%s fail to allocate output ctxt", __func__);
8617 ret = -ENOMEM;
8618 goto error_open;
8619 }
8620 out_ctxt->output = out;
8621
8622 pthread_mutex_lock(&adev->lock);
8623 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8624 pthread_mutex_unlock(&adev->lock);
8625
Eric Laurent994a6932013-07-17 11:51:42 -07008626 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008627 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008628
8629error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308630 if (out->convert_buffer)
8631 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008632 free(out);
8633 *stream_out = NULL;
8634 ALOGD("%s: exit: ret %d", __func__, ret);
8635 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008636}
8637
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308638void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008639 struct audio_stream_out *stream)
8640{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008641 struct stream_out *out = (struct stream_out *)stream;
8642 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008643 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008644
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008645 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308646
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008647 io_streams_map_remove(adev, out->handle);
8648
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308649 // must deregister from sndmonitor first to prevent races
8650 // between the callback and close_stream
8651 audio_extn_snd_mon_unregister_listener(out);
8652
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008653 /* close adsp hdrl session before standby */
8654 if (out->adsp_hdlr_stream_handle) {
8655 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8656 if (ret)
8657 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8658 out->adsp_hdlr_stream_handle = NULL;
8659 }
8660
Manish Dewangan21a850a2017-08-14 12:03:55 +05308661 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008662 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8663 out->ip_hdlr_handle = NULL;
8664 }
8665
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008666 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308667 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008668 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308669 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308670 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008671 if(ret != 0)
8672 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8673 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008674 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008675 out_standby(&stream->common);
8676
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008677 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008678 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008679 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008680 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008681 if (out->compr_config.codec != NULL)
8682 free(out->compr_config.codec);
8683 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008684
Zhou Song1f93fa52020-11-20 13:57:39 +08008685 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308686
Varun Balaraje49253e2017-07-06 19:48:56 +05308687 if (is_interactive_usecase(out->usecase))
8688 free_interactive_usecase(adev, out->usecase);
8689
Ashish Jain83a6cc22016-06-28 14:34:17 +05308690 if (out->convert_buffer != NULL) {
8691 free(out->convert_buffer);
8692 out->convert_buffer = NULL;
8693 }
8694
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008695 if (adev->voice_tx_output == out)
8696 adev->voice_tx_output = NULL;
8697
Aalique Grahame22e49102018-12-18 14:23:57 -08008698 error_log_destroy(out->error_log);
8699 out->error_log = NULL;
8700
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308701 if (adev->primary_output == out)
8702 adev->primary_output = NULL;
8703
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008704 pthread_cond_destroy(&out->cond);
8705 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008706 pthread_mutex_destroy(&out->pre_lock);
8707 pthread_mutex_destroy(&out->latch_lock);
8708 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008709
8710 pthread_mutex_lock(&adev->lock);
8711 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8712 if (out_ctxt != NULL) {
8713 list_remove(&out_ctxt->list);
8714 free(out_ctxt);
8715 } else {
8716 ALOGW("%s, output stream already closed", __func__);
8717 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008718 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008719 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008720 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008721}
8722
8723static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8724{
8725 struct audio_device *adev = (struct audio_device *)dev;
8726 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008727 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008728 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008729 int ret;
8730 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008731 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008732 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008733 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008734
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008735 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008736 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008737
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308738 if (!parms)
8739 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308740
Derek Chen6f293672019-04-01 01:40:24 -07008741 /* notify adev and input/output streams on the snd card status */
8742 adev_snd_mon_cb((void *)adev, parms);
8743
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008744 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8745 if (ret >= 0) {
8746 list_for_each(node, &adev->active_outputs_list) {
8747 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8748 streams_output_ctxt_t,
8749 list);
8750 out_snd_mon_cb((void *)out_ctxt->output, parms);
8751 }
Derek Chen6f293672019-04-01 01:40:24 -07008752
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008753 list_for_each(node, &adev->active_inputs_list) {
8754 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8755 streams_input_ctxt_t,
8756 list);
8757 in_snd_mon_cb((void *)in_ctxt->input, parms);
8758 }
Derek Chen6f293672019-04-01 01:40:24 -07008759 }
8760
Zhou Songd6d71752019-05-21 18:08:51 +08008761 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308762 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8763 if (ret >= 0) {
8764 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008765 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308766 adev->bt_sco_on = true;
Shalini Manjunathac8cd3e92021-02-01 12:23:49 +05308767 /*
8768 * When ever BT_SCO=ON arrives, make sure to route
8769 * all use cases to SCO device, otherwise due to delay in
8770 * BT_SCO=ON and lack of synchronization with create audio patch
8771 * request for SCO device, some times use case not routed properly to
8772 * SCO device
8773 */
8774 struct audio_usecase *usecase;
8775 struct listnode *node;
8776 list_for_each(node, &adev->usecase_list) {
8777 usecase = node_to_item(node, struct audio_usecase, list);
Anver sadhiqueb545d0c2021-09-03 15:25:44 +05308778 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Anver sadhiquea95c9f12021-08-11 11:19:45 +05308779 (!is_btsco_device(SND_DEVICE_NONE, usecase->in_snd_device)) && (is_sco_in_device_type(&usecase->stream.in->device_list))) {
Shalini Manjunathac8cd3e92021-02-01 12:23:49 +05308780 ALOGD("BT_SCO ON, switch all in use case to it");
8781 select_devices(adev, usecase->id);
8782 }
Mingshu Pang651036e2021-04-22 10:35:00 +08008783 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK ||
8784 usecase->type == VOICE_CALL) &&
Anver sadhiquea95c9f12021-08-11 11:19:45 +05308785 (!is_btsco_device(usecase->out_snd_device, SND_DEVICE_NONE)) && (is_sco_out_device_type(&usecase->stream.out->device_list))) {
Shalini Manjunathac8cd3e92021-02-01 12:23:49 +05308786 ALOGD("BT_SCO ON, switch all out use case to it");
8787 select_devices(adev, usecase->id);
8788 }
8789 }
8790 }
8791 else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308792 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008793 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008794 }
8795 }
8796
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008797 status = voice_set_parameters(adev, parms);
8798 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008799 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008800
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008801 status = platform_set_parameters(adev->platform, parms);
8802 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008803 goto done;
8804
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008805 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8806 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008807 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008808 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8809 adev->bluetooth_nrec = true;
8810 else
8811 adev->bluetooth_nrec = false;
8812 }
8813
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008814 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8815 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008816 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8817 adev->screen_off = false;
8818 else
8819 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008820 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008821 }
8822
Eric Laurent4b084132018-10-19 17:33:43 -07008823 ret = str_parms_get_int(parms, "rotation", &val);
8824 if (ret >= 0) {
8825 bool reverse_speakers = false;
8826 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8827 switch (val) {
8828 // FIXME: note that the code below assumes that the speakers are in the correct placement
8829 // relative to the user when the device is rotated 90deg from its default rotation. This
8830 // assumption is device-specific, not platform-specific like this code.
8831 case 270:
8832 reverse_speakers = true;
8833 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8834 break;
8835 case 0:
8836 case 180:
8837 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8838 break;
8839 case 90:
8840 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8841 break;
8842 default:
8843 ALOGE("%s: unexpected rotation of %d", __func__, val);
8844 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008845 }
Eric Laurent4b084132018-10-19 17:33:43 -07008846 if (status == 0) {
8847 // check and set swap
8848 // - check if orientation changed and speaker active
8849 // - set rotation and cache the rotation value
8850 adev->camera_orientation =
8851 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8852 if (!audio_extn_is_maxx_audio_enabled())
8853 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8854 }
8855 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008856
Mingming Yin514a8bc2014-07-29 15:22:21 -07008857 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8858 if (ret >= 0) {
8859 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8860 adev->bt_wb_speech_enabled = true;
8861 else
8862 adev->bt_wb_speech_enabled = false;
8863 }
8864
Zhou Song12c29502019-03-16 10:37:18 +08008865 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8866 if (ret >= 0) {
8867 val = atoi(value);
8868 adev->swb_speech_mode = val;
8869 }
8870
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008871 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8872 if (ret >= 0) {
8873 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308874 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008875 if (audio_is_output_device(val) &&
8876 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008877 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008878 platform_get_controller_stream_from_params(parms, &controller, &stream);
8879 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8880 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008881 if (ret < 0) {
8882 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308883 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008884 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008885 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308886 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008887 /*
8888 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8889 * Per AudioPolicyManager, USB device is higher priority than WFD.
8890 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8891 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8892 * starting voice call on USB
8893 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008894 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308895 if (ret >= 0)
8896 audio_extn_usb_add_device(device, atoi(value));
8897
Zhou Song6f862822017-11-06 17:27:57 +08008898 if (!audio_extn_usb_is_tunnel_supported()) {
8899 ALOGV("detected USB connect .. disable proxy");
8900 adev->allow_afe_proxy_usage = false;
8901 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008902 }
8903 }
8904
8905 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8906 if (ret >= 0) {
8907 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308908 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008909 /*
8910 * The HDMI / Displayport disconnect handling has been moved to
8911 * audio extension to ensure that its parameters are not
8912 * invalidated prior to updating sysfs of the disconnect event
8913 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8914 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308915 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008916 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308917 if (ret >= 0)
8918 audio_extn_usb_remove_device(device, atoi(value));
8919
Zhou Song6f862822017-11-06 17:27:57 +08008920 if (!audio_extn_usb_is_tunnel_supported()) {
8921 ALOGV("detected USB disconnect .. enable proxy");
8922 adev->allow_afe_proxy_usage = true;
8923 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008924 }
8925 }
8926
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008927 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008928
8929 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008930 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308931 struct audio_usecase *usecase;
8932 struct listnode *node;
8933 list_for_each(node, &adev->usecase_list) {
8934 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008935 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8936 continue;
8937
8938 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308939 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308940 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308941 ALOGD("Switching to speaker and muting the stream before select_devices");
8942 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308943 //force device switch to re configure encoder
8944 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308945 ALOGD("Unmuting the stream after select_devices");
Zhou Song1f93fa52020-11-20 13:57:39 +08008946 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308947 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308948 break;
Zhou Song9ebf6792020-09-23 22:49:01 +08008949 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008950 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08008951 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008952 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8953 reassign_device_list(&usecase->stream.out->device_list,
8954 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8955 check_a2dp_restore_l(adev, usecase->stream.out, true);
8956 break;
8957 }
8958 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308959 }
8960 }
8961 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008962
8963 //handle vr audio setparam
8964 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8965 value, sizeof(value));
8966 if (ret >= 0) {
8967 ALOGI("Setting vr mode to be %s", value);
8968 if (!strncmp(value, "true", 4)) {
8969 adev->vr_audio_mode_enabled = true;
8970 ALOGI("Setting vr mode to true");
8971 } else if (!strncmp(value, "false", 5)) {
8972 adev->vr_audio_mode_enabled = false;
8973 ALOGI("Setting vr mode to false");
8974 } else {
8975 ALOGI("wrong vr mode set");
8976 }
8977 }
8978
Eric Laurent4b084132018-10-19 17:33:43 -07008979 //FIXME: to be replaced by proper video capture properties API
8980 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8981 if (ret >= 0) {
8982 int camera_facing = CAMERA_FACING_BACK;
8983 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8984 camera_facing = CAMERA_FACING_FRONT;
8985 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8986 camera_facing = CAMERA_FACING_BACK;
8987 else {
8988 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8989 goto done;
8990 }
8991 adev->camera_orientation =
8992 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8993 struct audio_usecase *usecase;
8994 struct listnode *node;
8995 list_for_each(node, &adev->usecase_list) {
8996 usecase = node_to_item(node, struct audio_usecase, list);
8997 struct stream_in *in = usecase->stream.in;
8998 if (usecase->type == PCM_CAPTURE && in != NULL &&
8999 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
9000 select_devices(adev, in->usecase);
9001 }
9002 }
9003 }
9004
Naresh Tannirucd2353e2016-08-19 00:37:25 +05309005 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08009006done:
9007 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009008 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05309009error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009010 ALOGV("%s: exit with code(%d)", __func__, status);
9011 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009012}
9013
9014static char* adev_get_parameters(const struct audio_hw_device *dev,
9015 const char *keys)
9016{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309017 ALOGD("%s:%s", __func__, keys);
9018
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009019 struct audio_device *adev = (struct audio_device *)dev;
9020 struct str_parms *reply = str_parms_create();
9021 struct str_parms *query = str_parms_create_str(keys);
9022 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309023 char value[256] = {0};
9024 int ret = 0;
9025
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009026 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009027 if (reply) {
9028 str_parms_destroy(reply);
9029 }
9030 if (query) {
9031 str_parms_destroy(query);
9032 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009033 ALOGE("adev_get_parameters: failed to create query or reply");
9034 return NULL;
9035 }
9036
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009037 //handle vr audio getparam
9038
9039 ret = str_parms_get_str(query,
9040 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9041 value, sizeof(value));
9042
9043 if (ret >= 0) {
9044 bool vr_audio_enabled = false;
9045 pthread_mutex_lock(&adev->lock);
9046 vr_audio_enabled = adev->vr_audio_mode_enabled;
9047 pthread_mutex_unlock(&adev->lock);
9048
9049 ALOGI("getting vr mode to %d", vr_audio_enabled);
9050
9051 if (vr_audio_enabled) {
9052 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9053 "true");
9054 goto exit;
9055 } else {
9056 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9057 "false");
9058 goto exit;
9059 }
9060 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009061
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009062 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009063 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009064 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009065 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009066 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009067 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309068 pthread_mutex_unlock(&adev->lock);
9069
Naresh Tannirud7205b62014-06-20 02:54:48 +05309070exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009071 str = str_parms_to_str(reply);
9072 str_parms_destroy(query);
9073 str_parms_destroy(reply);
9074
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309075 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009076 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009077}
9078
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009079static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009080{
9081 return 0;
9082}
9083
9084static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9085{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009086 int ret;
9087 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009088
9089 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9090
Haynes Mathew George5191a852013-09-11 14:19:36 -07009091 pthread_mutex_lock(&adev->lock);
9092 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009093 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009094 pthread_mutex_unlock(&adev->lock);
9095 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009096}
9097
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009098static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9099 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009100{
9101 return -ENOSYS;
9102}
9103
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009104static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9105 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009106{
9107 return -ENOSYS;
9108}
9109
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009110static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9111 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112{
9113 return -ENOSYS;
9114}
9115
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009116static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9117 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009118{
9119 return -ENOSYS;
9120}
9121
9122static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9123{
9124 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009125 struct listnode *node;
9126 struct audio_usecase *usecase = NULL;
9127 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009129 pthread_mutex_lock(&adev->lock);
9130 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309131 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9132 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009133 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009134 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309135 adev->current_call_output = adev->primary_output;
9136 voice_start_call(adev);
9137 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009138 (mode == AUDIO_MODE_NORMAL ||
9139 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009140 list_for_each(node, &adev->usecase_list) {
9141 usecase = node_to_item(node, struct audio_usecase, list);
9142 if (usecase->type == VOICE_CALL)
9143 break;
9144 }
9145 if (usecase &&
9146 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9147 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9148 true);
9149 if (ret != 0) {
9150 /* default service interval was successfully updated,
9151 reopen USB backend with new service interval */
9152 check_usecases_codec_backend(adev,
9153 usecase,
9154 usecase->out_snd_device);
9155 }
9156 }
9157
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009158 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009159 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009160 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009161 // restore device for other active usecases after stop call
9162 list_for_each(node, &adev->usecase_list) {
9163 usecase = node_to_item(node, struct audio_usecase, list);
9164 select_devices(adev, usecase->id);
9165 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009166 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009167 }
9168 pthread_mutex_unlock(&adev->lock);
9169 return 0;
9170}
9171
9172static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9173{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009174 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009175 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009176
9177 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009178 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009179 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009180
Derek Chend2530072014-11-24 12:39:14 -08009181 if (adev->ext_hw_plugin)
9182 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009183
9184 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009185 pthread_mutex_unlock(&adev->lock);
9186
9187 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009188}
9189
9190static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9191{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009192 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009193 return 0;
9194}
9195
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009196static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009197 const struct audio_config *config)
9198{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009199 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009200
Aalique Grahame22e49102018-12-18 14:23:57 -08009201 /* Don't know if USB HIFI in this context so use true to be conservative */
9202 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9203 true /*is_usb_hifi */) != 0)
9204 return 0;
9205
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009206 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9207 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009208}
9209
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009210static bool adev_input_allow_hifi_record(struct audio_device *adev,
9211 audio_devices_t devices,
9212 audio_input_flags_t flags,
9213 audio_source_t source) {
9214 const bool allowed = true;
9215
9216 if (!audio_is_usb_in_device(devices))
9217 return !allowed;
9218
9219 switch (flags) {
9220 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009221 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009222 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9223 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009224 default:
9225 return !allowed;
9226 }
9227
9228 switch (source) {
9229 case AUDIO_SOURCE_DEFAULT:
9230 case AUDIO_SOURCE_MIC:
9231 case AUDIO_SOURCE_UNPROCESSED:
9232 break;
9233 default:
9234 return !allowed;
9235 }
9236
9237 switch (adev->mode) {
9238 case 0:
9239 break;
9240 default:
9241 return !allowed;
9242 }
9243
9244 return allowed;
9245}
9246
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009247static int adev_update_voice_comm_input_stream(struct stream_in *in,
9248 struct audio_config *config)
9249{
9250 bool valid_rate = (config->sample_rate == 8000 ||
9251 config->sample_rate == 16000 ||
9252 config->sample_rate == 32000 ||
9253 config->sample_rate == 48000);
9254 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9255
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009256 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009257 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009258 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9259 in->config = default_pcm_config_voip_copp;
9260 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9261 DEFAULT_VOIP_BUF_DURATION_MS,
9262 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009263 } else {
9264 ALOGW("%s No valid input in voip, use defaults"
9265 "sample rate %u, channel mask 0x%X",
9266 __func__, config->sample_rate, in->channel_mask);
9267 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009268 in->config.rate = config->sample_rate;
9269 in->sample_rate = config->sample_rate;
9270 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009271 //XXX needed for voice_extn_compress_voip_open_input_stream
9272 in->config.rate = config->sample_rate;
9273 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309274 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009275 voice_extn_compress_voip_is_active(in->dev)) &&
9276 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9277 valid_rate && valid_ch) {
9278 voice_extn_compress_voip_open_input_stream(in);
9279 // update rate entries to match config from AF
9280 in->config.rate = config->sample_rate;
9281 in->sample_rate = config->sample_rate;
9282 } else {
9283 ALOGW("%s compress voip not active, use defaults", __func__);
9284 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009285 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009286 return 0;
9287}
9288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009289static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009290 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009291 audio_devices_t devices,
9292 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009293 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309294 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009295 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009296 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009297{
9298 struct audio_device *adev = (struct audio_device *)dev;
9299 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009300 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009301 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009302 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309303 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009304 bool is_usb_dev = audio_is_usb_in_device(devices);
9305 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9306 devices,
9307 flags,
9308 source);
Andy Hung94320602018-10-29 18:31:12 -07009309 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9310 " sample_rate %u, channel_mask %#x, format %#x",
9311 __func__, flags, is_usb_dev, may_use_hifi_record,
9312 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309313
kunleizdff872d2018-08-20 14:40:33 +08009314 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009315 is_usb_dev = false;
9316 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9317 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9318 __func__, devices);
9319 }
9320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009321 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009322
9323 if (!(is_usb_dev && may_use_hifi_record)) {
9324 if (config->sample_rate == 0)
9325 config->sample_rate = 48000;
9326 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9327 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9328 if (config->format == AUDIO_FORMAT_DEFAULT)
9329 config->format = AUDIO_FORMAT_PCM_16_BIT;
9330
9331 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9332
Aalique Grahame22e49102018-12-18 14:23:57 -08009333 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9334 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009335 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309336 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009337
Rahul Sharma99770982019-03-06 17:05:26 +05309338 pthread_mutex_lock(&adev->lock);
9339 if (in_get_stream(adev, handle) != NULL) {
9340 ALOGW("%s, input stream already opened", __func__);
9341 ret = -EEXIST;
9342 }
9343 pthread_mutex_unlock(&adev->lock);
9344 if (ret)
9345 return ret;
9346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009347 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009348
9349 if (!in) {
9350 ALOGE("failed to allocate input stream");
9351 return -ENOMEM;
9352 }
9353
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309354 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309355 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9356 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009357 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009358 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009360 in->stream.common.get_sample_rate = in_get_sample_rate;
9361 in->stream.common.set_sample_rate = in_set_sample_rate;
9362 in->stream.common.get_buffer_size = in_get_buffer_size;
9363 in->stream.common.get_channels = in_get_channels;
9364 in->stream.common.get_format = in_get_format;
9365 in->stream.common.set_format = in_set_format;
9366 in->stream.common.standby = in_standby;
9367 in->stream.common.dump = in_dump;
9368 in->stream.common.set_parameters = in_set_parameters;
9369 in->stream.common.get_parameters = in_get_parameters;
9370 in->stream.common.add_audio_effect = in_add_audio_effect;
9371 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9372 in->stream.set_gain = in_set_gain;
9373 in->stream.read = in_read;
9374 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009375 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309376 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009377 in->stream.set_microphone_direction = in_set_microphone_direction;
9378 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009379 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009380
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009381 list_init(&in->device_list);
9382 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009383 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009384 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009385 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009386 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009387 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009388 in->bit_width = 16;
9389 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009390 in->direction = MIC_DIRECTION_UNSPECIFIED;
9391 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009392 list_init(&in->aec_list);
9393 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009394 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009395
Andy Hung94320602018-10-29 18:31:12 -07009396 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009397 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9398 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9399 /* Force channel config requested to mono if incall
9400 record is being requested for only uplink/downlink */
9401 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9402 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9403 ret = -EINVAL;
9404 goto err_open;
9405 }
9406 }
9407
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009408 if (is_usb_dev && may_use_hifi_record) {
9409 /* HiFi record selects an appropriate format, channel, rate combo
9410 depending on sink capabilities*/
9411 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9412 &config->format,
9413 &in->supported_formats[0],
9414 MAX_SUPPORTED_FORMATS,
9415 &config->channel_mask,
9416 &in->supported_channel_masks[0],
9417 MAX_SUPPORTED_CHANNEL_MASKS,
9418 &config->sample_rate,
9419 &in->supported_sample_rates[0],
9420 MAX_SUPPORTED_SAMPLE_RATES);
9421 if (ret != 0) {
9422 ret = -EINVAL;
9423 goto err_open;
9424 }
9425 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009426 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309427 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309428 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9429 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9430 in->config.format = PCM_FORMAT_S32_LE;
9431 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309432 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9433 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9434 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9435 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9436 bool ret_error = false;
9437 in->bit_width = 24;
9438 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9439 from HAL is 24_packed and 8_24
9440 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9441 24_packed return error indicating supported format is 24_packed
9442 *> In case of any other source requesting 24 bit or float return error
9443 indicating format supported is 16 bit only.
9444
9445 on error flinger will retry with supported format passed
9446 */
9447 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9448 (source != AUDIO_SOURCE_CAMCORDER)) {
9449 config->format = AUDIO_FORMAT_PCM_16_BIT;
9450 if (config->sample_rate > 48000)
9451 config->sample_rate = 48000;
9452 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009453 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9454 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309455 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9456 ret_error = true;
9457 }
9458
9459 if (ret_error) {
9460 ret = -EINVAL;
9461 goto err_open;
9462 }
9463 }
9464
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009465 in->channel_mask = config->channel_mask;
9466 in->format = config->format;
9467
9468 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309469
9470 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9471 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9472 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9473 else {
9474 ret = -EINVAL;
9475 goto err_open;
9476 }
9477 }
9478
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009479 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309480 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9481 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009482 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9483 is_low_latency = true;
9484#if LOW_LATENCY_CAPTURE_USE_CASE
9485 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9486#endif
9487 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009488 if (!in->realtime) {
9489 in->config = pcm_config_audio_capture;
9490 frame_size = audio_stream_in_frame_size(&in->stream);
9491 buffer_size = get_input_buffer_size(config->sample_rate,
9492 config->format,
9493 channel_count,
9494 is_low_latency);
9495 in->config.period_size = buffer_size / frame_size;
9496 in->config.rate = config->sample_rate;
9497 in->af_period_multiplier = 1;
9498 } else {
9499 // period size is left untouched for rt mode playback
9500 in->config = pcm_config_audio_capture_rt;
9501 in->af_period_multiplier = af_period_multiplier;
9502 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009503 }
9504
9505 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9506 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9507 in->realtime = 0;
9508 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9509 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009510 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009511 in->stream.start = in_start;
9512 in->stream.stop = in_stop;
9513 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9514 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009515 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009516 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009517 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9518 in->config = pcm_config_audio_capture;
9519 frame_size = audio_stream_in_frame_size(&in->stream);
9520 buffer_size = get_input_buffer_size(config->sample_rate,
9521 config->format,
9522 channel_count,
9523 false /*is_low_latency*/);
9524 in->config.period_size = buffer_size / frame_size;
9525 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009526 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009527 switch (config->format) {
9528 case AUDIO_FORMAT_PCM_32_BIT:
9529 in->bit_width = 32;
9530 break;
9531 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9532 case AUDIO_FORMAT_PCM_8_24_BIT:
9533 in->bit_width = 24;
9534 break;
9535 default:
9536 in->bit_width = 16;
9537 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009538 } else if (is_single_device_type_equal(&in->device_list,
9539 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9540 is_single_device_type_equal(&in->device_list,
9541 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009542 if (config->sample_rate == 0)
9543 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9544 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9545 config->sample_rate != 8000) {
9546 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9547 ret = -EINVAL;
9548 goto err_open;
9549 }
9550 if (config->format == AUDIO_FORMAT_DEFAULT)
9551 config->format = AUDIO_FORMAT_PCM_16_BIT;
9552 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9553 config->format = AUDIO_FORMAT_PCM_16_BIT;
9554 ret = -EINVAL;
9555 goto err_open;
9556 }
9557
9558 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009559 if (adev->ha_proxy_enable &&
9560 is_single_device_type_equal(&in->device_list,
9561 AUDIO_DEVICE_IN_TELEPHONY_RX))
9562 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009563 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009564 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009565 in->af_period_multiplier = 1;
9566 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaabdf7482020-01-03 15:00:14 +05309567 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009568 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9569 (config->sample_rate == 8000 ||
9570 config->sample_rate == 16000 ||
9571 config->sample_rate == 32000 ||
9572 config->sample_rate == 48000) &&
9573 channel_count == 1) {
9574 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9575 in->config = pcm_config_audio_capture;
9576 frame_size = audio_stream_in_frame_size(&in->stream);
9577 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9578 config->sample_rate,
9579 config->format,
9580 channel_count, false /*is_low_latency*/);
9581 in->config.period_size = buffer_size / frame_size;
9582 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9583 in->config.rate = config->sample_rate;
9584 in->af_period_multiplier = 1;
Mingshu Pang7b59b5e2021-01-14 16:19:10 +08009585 } else if (in->realtime) {
9586 in->config = pcm_config_audio_capture_rt;
9587 in->config.format = pcm_format_from_audio_format(config->format);
9588 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009589 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309590 int ret_val;
9591 pthread_mutex_lock(&adev->lock);
9592 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9593 in, config, &channel_mask_updated);
9594 pthread_mutex_unlock(&adev->lock);
9595
9596 if (!ret_val) {
9597 if (channel_mask_updated == true) {
9598 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9599 __func__, config->channel_mask);
9600 ret = -EINVAL;
9601 goto err_open;
9602 }
9603 ALOGD("%s: created multi-channel session succesfully",__func__);
9604 } else if (audio_extn_compr_cap_enabled() &&
9605 audio_extn_compr_cap_format_supported(config->format) &&
9606 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9607 audio_extn_compr_cap_init(in);
9608 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309609 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309610 if (ret)
9611 goto err_open;
9612 } else {
9613 in->config = pcm_config_audio_capture;
9614 in->config.rate = config->sample_rate;
9615 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309616 in->format = config->format;
9617 frame_size = audio_stream_in_frame_size(&in->stream);
9618 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009619 config->format,
9620 channel_count,
9621 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009622 /* prevent division-by-zero */
9623 if (frame_size == 0) {
9624 ALOGE("%s: Error frame_size==0", __func__);
9625 ret = -EINVAL;
9626 goto err_open;
9627 }
9628
Revathi Uddarajud2634032017-12-07 14:42:34 +05309629 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009630 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009631
Revathi Uddarajud2634032017-12-07 14:42:34 +05309632 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9633 /* optionally use VOIP usecase depending on config(s) */
9634 ret = adev_update_voice_comm_input_stream(in, config);
9635 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009636
Revathi Uddarajud2634032017-12-07 14:42:34 +05309637 if (ret) {
9638 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9639 goto err_open;
9640 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009641 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309642
9643 /* assign concurrent capture usecase if record has to caried out from
9644 * actual hardware input source */
9645 if (audio_extn_is_concurrent_capture_enabled() &&
9646 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309647 /* Acquire lock to avoid two concurrent use cases initialized to
9648 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009649
Samyak Jainc37062f2019-04-25 18:41:06 +05309650 if (in->usecase == USECASE_AUDIO_RECORD) {
9651 pthread_mutex_lock(&adev->lock);
9652 if (!(adev->pcm_record_uc_state)) {
9653 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9654 adev->pcm_record_uc_state = 1;
9655 pthread_mutex_unlock(&adev->lock);
9656 } else {
9657 pthread_mutex_unlock(&adev->lock);
9658 /* Assign compress record use case for second record */
9659 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9660 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9661 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9662 if (audio_extn_cin_applicable_stream(in)) {
9663 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309664 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309665 if (ret)
9666 goto err_open;
9667 }
9668 }
9669 }
kunleiz28c73e72019-03-27 17:24:04 +08009670 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009671 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309672 if (audio_extn_ssr_get_stream() != in)
9673 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009674
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009675 in->sample_rate = in->config.rate;
9676
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309677 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9678 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009679 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009680 in->sample_rate, in->bit_width,
9681 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309682 register_format(in->format, in->supported_formats);
9683 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9684 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309685
Aalique Grahame22e49102018-12-18 14:23:57 -08009686 in->error_log = error_log_create(
9687 ERROR_LOG_ENTRIES,
9688 1000000000 /* aggregate consecutive identical errors within one second */);
9689
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009690 /* This stream could be for sound trigger lab,
9691 get sound trigger pcm if present */
9692 audio_extn_sound_trigger_check_and_get_session(in);
9693
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309694 lock_input_stream(in);
9695 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9696 pthread_mutex_lock(&adev->lock);
9697 in->card_status = adev->card_status;
9698 pthread_mutex_unlock(&adev->lock);
9699 pthread_mutex_unlock(&in->lock);
9700
Aalique Grahame22e49102018-12-18 14:23:57 -08009701 stream_app_type_cfg_init(&in->app_type_cfg);
9702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009703 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009704
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009705 ret = io_streams_map_insert(adev, &in->stream.common,
9706 handle, AUDIO_PATCH_HANDLE_NONE);
9707 if (ret != 0)
9708 goto err_open;
9709
Derek Chenf939fb72018-11-13 13:34:41 -08009710 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9711 calloc(1, sizeof(streams_input_ctxt_t));
9712 if (in_ctxt == NULL) {
9713 ALOGE("%s fail to allocate input ctxt", __func__);
9714 ret = -ENOMEM;
9715 goto err_open;
9716 }
9717 in_ctxt->input = in;
9718
9719 pthread_mutex_lock(&adev->lock);
9720 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9721 pthread_mutex_unlock(&adev->lock);
9722
Eric Laurent994a6932013-07-17 11:51:42 -07009723 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009724 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009725
9726err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309727 if (in->usecase == USECASE_AUDIO_RECORD) {
9728 pthread_mutex_lock(&adev->lock);
9729 adev->pcm_record_uc_state = 0;
9730 pthread_mutex_unlock(&adev->lock);
9731 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009732 free(in);
9733 *stream_in = NULL;
9734 return ret;
9735}
9736
9737static void adev_close_input_stream(struct audio_hw_device *dev,
9738 struct audio_stream_in *stream)
9739{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009740 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009741 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009742 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309743
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309744 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009745
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009746 if (in == NULL) {
9747 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9748 return;
9749 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009750 io_streams_map_remove(adev, in->capture_handle);
9751
kunleiz70e57612018-12-28 17:50:23 +08009752 /* must deregister from sndmonitor first to prevent races
9753 * between the callback and close_stream
9754 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309755 audio_extn_snd_mon_unregister_listener(stream);
9756
kunleiz70e57612018-12-28 17:50:23 +08009757 /* Disable echo reference if there are no active input, hfp call
9758 * and sound trigger while closing input stream
9759 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009760 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009761 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009762 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9763 struct listnode out_devices;
9764 list_init(&out_devices);
9765 platform_set_echo_reference(adev, false, &out_devices);
9766 } else
kunleiz70e57612018-12-28 17:50:23 +08009767 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309768
Weiyin Jiang2995f662019-04-17 14:25:12 +08009769 error_log_destroy(in->error_log);
9770 in->error_log = NULL;
9771
Pallavid7c7a272018-01-16 11:22:55 +05309772
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009773 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309774 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009775 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309776 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009777 if (ret != 0)
9778 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9779 __func__, ret);
9780 } else
9781 in_standby(&stream->common);
9782
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009783 pthread_mutex_destroy(&in->lock);
9784 pthread_mutex_destroy(&in->pre_lock);
9785
Revathi Uddarajud2634032017-12-07 14:42:34 +05309786 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309787 if (in->usecase == USECASE_AUDIO_RECORD) {
9788 adev->pcm_record_uc_state = 0;
9789 }
9790
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009791 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9792 adev->enable_voicerx = false;
9793 }
9794
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009795 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009796 audio_extn_ssr_deinit();
9797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009798
Garmond Leunge2433c32017-09-28 21:51:22 -07009799 if (audio_extn_ffv_get_stream() == in) {
9800 audio_extn_ffv_stream_deinit();
9801 }
9802
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309803 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009804 audio_extn_compr_cap_format_supported(in->config.format))
9805 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309806
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309807 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309808 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009809
Mingming Yinfd7607b2016-01-22 12:48:44 -08009810 if (in->is_st_session) {
9811 ALOGV("%s: sound trigger pcm stop lab", __func__);
9812 audio_extn_sound_trigger_stop_lab(in);
9813 }
Derek Chenf939fb72018-11-13 13:34:41 -08009814 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9815 if (in_ctxt != NULL) {
9816 list_remove(&in_ctxt->list);
9817 free(in_ctxt);
9818 } else {
9819 ALOGW("%s, input stream already closed", __func__);
9820 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009821 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309822 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009823 return;
9824}
9825
Aalique Grahame22e49102018-12-18 14:23:57 -08009826/* verifies input and output devices and their capabilities.
9827 *
9828 * This verification is required when enabling extended bit-depth or
9829 * sampling rates, as not all qcom products support it.
9830 *
9831 * Suitable for calling only on initialization such as adev_open().
9832 * It fills the audio_device use_case_table[] array.
9833 *
9834 * Has a side-effect that it needs to configure audio routing / devices
9835 * in order to power up the devices and read the device parameters.
9836 * It does not acquire any hw device lock. Should restore the devices
9837 * back to "normal state" upon completion.
9838 */
9839static int adev_verify_devices(struct audio_device *adev)
9840{
9841 /* enumeration is a bit difficult because one really wants to pull
9842 * the use_case, device id, etc from the hidden pcm_device_table[].
9843 * In this case there are the following use cases and device ids.
9844 *
9845 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9846 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9847 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9848 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9849 * [USECASE_AUDIO_RECORD] = {0, 0},
9850 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9851 * [USECASE_VOICE_CALL] = {2, 2},
9852 *
9853 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9854 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9855 */
9856
9857 /* should be the usecases enabled in adev_open_input_stream() */
9858 static const int test_in_usecases[] = {
9859 USECASE_AUDIO_RECORD,
9860 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9861 };
9862 /* should be the usecases enabled in adev_open_output_stream()*/
9863 static const int test_out_usecases[] = {
9864 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9865 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9866 };
9867 static const usecase_type_t usecase_type_by_dir[] = {
9868 PCM_PLAYBACK,
9869 PCM_CAPTURE,
9870 };
9871 static const unsigned flags_by_dir[] = {
9872 PCM_OUT,
9873 PCM_IN,
9874 };
9875
9876 size_t i;
9877 unsigned dir;
9878 const unsigned card_id = adev->snd_card;
9879
9880 for (dir = 0; dir < 2; ++dir) {
9881 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9882 const unsigned flags_dir = flags_by_dir[dir];
9883 const size_t testsize =
9884 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9885 const int *testcases =
9886 dir ? test_in_usecases : test_out_usecases;
9887 const audio_devices_t audio_device =
9888 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9889
9890 for (i = 0; i < testsize; ++i) {
9891 const audio_usecase_t audio_usecase = testcases[i];
9892 int device_id;
9893 struct pcm_params **pparams;
9894 struct stream_out out;
9895 struct stream_in in;
9896 struct audio_usecase uc_info;
9897 int retval;
9898
9899 pparams = &adev->use_case_table[audio_usecase];
9900 pcm_params_free(*pparams); /* can accept null input */
9901 *pparams = NULL;
9902
9903 /* find the device ID for the use case (signed, for error) */
9904 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9905 if (device_id < 0)
9906 continue;
9907
9908 /* prepare structures for device probing */
9909 memset(&uc_info, 0, sizeof(uc_info));
9910 uc_info.id = audio_usecase;
9911 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009912 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009913 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009914 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009915 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009916 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009917 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9918 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009919 }
9920 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009921 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009922 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009923 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009924 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009925 uc_info.in_snd_device = SND_DEVICE_NONE;
9926 uc_info.out_snd_device = SND_DEVICE_NONE;
9927 list_add_tail(&adev->usecase_list, &uc_info.list);
9928
9929 /* select device - similar to start_(in/out)put_stream() */
9930 retval = select_devices(adev, audio_usecase);
9931 if (retval >= 0) {
9932 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9933#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009934 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009935 if (*pparams) {
9936 ALOGV("%s: (%s) card %d device %d", __func__,
9937 dir ? "input" : "output", card_id, device_id);
9938 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9939 } else {
9940 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9941 }
9942#endif
9943 }
9944
9945 /* deselect device - similar to stop_(in/out)put_stream() */
9946 /* 1. Get and set stream specific mixer controls */
9947 retval = disable_audio_route(adev, &uc_info);
9948 /* 2. Disable the rx device */
9949 retval = disable_snd_device(adev,
9950 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9951 list_remove(&uc_info.list);
9952 }
9953 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009954 return 0;
9955}
9956
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009957int update_patch(unsigned int num_sources,
9958 const struct audio_port_config *sources,
9959 unsigned int num_sinks,
9960 const struct audio_port_config *sinks,
9961 audio_patch_handle_t handle,
9962 struct audio_patch_info *p_info,
9963 patch_type_t patch_type, bool new_patch)
9964{
9965 ALOGD("%s: enter", __func__);
9966
9967 if (p_info == NULL) {
9968 ALOGE("%s: Invalid patch pointer", __func__);
9969 return -EINVAL;
9970 }
9971
9972 if (new_patch) {
9973 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9974 if (p_info->patch == NULL) {
9975 ALOGE("%s: Could not allocate patch", __func__);
9976 return -ENOMEM;
9977 }
9978 }
9979
9980 p_info->patch->id = handle;
9981 p_info->patch->num_sources = num_sources;
9982 p_info->patch->num_sinks = num_sinks;
9983
9984 for (int i = 0; i < num_sources; i++)
9985 p_info->patch->sources[i] = sources[i];
9986 for (int i = 0; i < num_sinks; i++)
9987 p_info->patch->sinks[i] = sinks[i];
9988
9989 p_info->patch_type = patch_type;
9990 return 0;
9991}
9992
9993audio_patch_handle_t generate_patch_handle()
9994{
9995 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9996 if (++patch_handle < 0)
9997 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9998 return patch_handle;
9999}
10000
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010001int adev_create_audio_patch(struct audio_hw_device *dev,
10002 unsigned int num_sources,
10003 const struct audio_port_config *sources,
10004 unsigned int num_sinks,
10005 const struct audio_port_config *sinks,
10006 audio_patch_handle_t *handle)
10007{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010008 int ret = 0;
10009 struct audio_device *adev = (struct audio_device *)dev;
10010 struct audio_patch_info *p_info = NULL;
10011 patch_type_t patch_type = PATCH_NONE;
10012 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10013 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
10014 struct audio_stream_info *s_info = NULL;
10015 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010016 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010017 audio_devices_t device_type = AUDIO_DEVICE_NONE;
10018 bool new_patch = false;
10019 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010020
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010021 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10022 num_sources, num_sinks, *handle);
10023
10024 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10025 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10026 ALOGE("%s: Invalid patch arguments", __func__);
10027 ret = -EINVAL;
10028 goto done;
10029 }
10030
10031 if (num_sources > 1) {
10032 ALOGE("%s: Multiple sources are not supported", __func__);
10033 ret = -EINVAL;
10034 goto done;
10035 }
10036
10037 if (sources == NULL || sinks == NULL) {
10038 ALOGE("%s: Invalid sources or sinks port config", __func__);
10039 ret = -EINVAL;
10040 goto done;
10041 }
10042
10043 ALOGV("%s: source role %d, source type %d", __func__,
10044 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010045 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010046
10047 // Populate source/sink information and fetch stream info
10048 switch (sources[0].type) {
10049 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10050 device_type = sources[0].ext.device.type;
10051 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010052 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010053 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10054 patch_type = PATCH_CAPTURE;
10055 io_handle = sinks[0].ext.mix.handle;
10056 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010057 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010058 __func__, device_type, io_handle);
10059 } else {
10060 // Device to device patch is not implemented.
10061 // This space will need changes if audio HAL
10062 // handles device to device patches in the future.
10063 patch_type = PATCH_DEVICE_LOOPBACK;
10064 }
10065 break;
10066 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10067 io_handle = sources[0].ext.mix.handle;
10068 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010069 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010070 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010071 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 }
10073 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010074 ALOGD("%s: Playback patch from mix handle %d to device %x",
10075 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010076 break;
10077 case AUDIO_PORT_TYPE_SESSION:
10078 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010079 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10080 ret = -EINVAL;
10081 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010082 }
10083
10084 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010085
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086 // Generate patch info and update patch
10087 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010088 *handle = generate_patch_handle();
10089 p_info = (struct audio_patch_info *)
10090 calloc(1, sizeof(struct audio_patch_info));
10091 if (p_info == NULL) {
10092 ALOGE("%s: Failed to allocate memory", __func__);
10093 pthread_mutex_unlock(&adev->lock);
10094 ret = -ENOMEM;
10095 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010096 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010097 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010098 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010099 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 if (p_info == NULL) {
10101 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10102 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010103 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104 ret = -EINVAL;
10105 goto done;
10106 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010108 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010109 *handle, p_info, patch_type, new_patch);
10110
10111 // Fetch stream info of associated mix for playback or capture patches
10112 if (p_info->patch_type == PATCH_PLAYBACK ||
10113 p_info->patch_type == PATCH_CAPTURE) {
10114 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10115 if (s_info == NULL) {
10116 ALOGE("%s: Failed to obtain stream info", __func__);
10117 if (new_patch)
10118 free(p_info);
10119 pthread_mutex_unlock(&adev->lock);
10120 ret = -EINVAL;
10121 goto done;
10122 }
10123 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10124 s_info->patch_handle = *handle;
10125 stream = s_info->stream;
10126 }
10127 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010128
10129 // Update routing for stream
10130 if (stream != NULL) {
10131 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010132 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010133 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010134 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010135 if (ret < 0) {
10136 pthread_mutex_lock(&adev->lock);
10137 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10138 if (new_patch)
10139 free(p_info);
10140 pthread_mutex_unlock(&adev->lock);
10141 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10142 goto done;
10143 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144 }
10145
10146 // Add new patch to patch map
10147 if (!ret && new_patch) {
10148 pthread_mutex_lock(&adev->lock);
10149 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010150 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010151 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 }
10153
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010154done:
10155 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010156 num_sources,
10157 sources,
10158 num_sinks,
10159 sinks,
10160 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010161 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010162 num_sources,
10163 sources,
10164 num_sinks,
10165 sinks,
10166 handle);
10167 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010168}
10169
10170int adev_release_audio_patch(struct audio_hw_device *dev,
10171 audio_patch_handle_t handle)
10172{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010173 struct audio_device *adev = (struct audio_device *) dev;
10174 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010175 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010176 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010177
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010178 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10179 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10180 ret = -EINVAL;
10181 goto done;
10182 }
10183
10184 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010185 pthread_mutex_lock(&adev->lock);
10186 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 if (p_info == NULL) {
10188 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010189 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010190 ret = -EINVAL;
10191 goto done;
10192 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010193 struct audio_patch *patch = p_info->patch;
10194 if (patch == NULL) {
10195 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010196 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010197 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010198 goto done;
10199 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010200 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10201 switch (patch->sources[0].type) {
10202 case AUDIO_PORT_TYPE_MIX:
10203 io_handle = patch->sources[0].ext.mix.handle;
10204 break;
10205 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010206 if (p_info->patch_type == PATCH_CAPTURE)
10207 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010208 break;
10209 case AUDIO_PORT_TYPE_SESSION:
10210 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010211 pthread_mutex_unlock(&adev->lock);
10212 ret = -EINVAL;
10213 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010214 }
10215
10216 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010217 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010218 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010219 if (patch_type == PATCH_PLAYBACK ||
10220 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010221 struct audio_stream_info *s_info =
10222 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10223 if (s_info == NULL) {
10224 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10225 pthread_mutex_unlock(&adev->lock);
10226 goto done;
10227 }
10228 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10229 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010230 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010231 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010232
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010233 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010234 struct listnode devices;
10235 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010236 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010237 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010238 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010239 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010240 }
10241
10242 if (ret < 0)
10243 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10244
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010245done:
10246 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10247 audio_extn_auto_hal_release_audio_patch(dev, handle);
10248
10249 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010250 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010251}
10252
10253int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10254{
Derek Chenf13dd492018-11-13 14:53:51 -080010255 int ret = 0;
10256
10257 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10258 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10259 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010260}
10261
10262int adev_set_audio_port_config(struct audio_hw_device *dev,
10263 const struct audio_port_config *config)
10264{
Derek Chenf13dd492018-11-13 14:53:51 -080010265 int ret = 0;
10266
10267 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10268 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10269 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010270}
10271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010272static int adev_dump(const audio_hw_device_t *device __unused,
10273 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010274{
10275 return 0;
10276}
10277
10278static int adev_close(hw_device_t *device)
10279{
Aalique Grahame22e49102018-12-18 14:23:57 -080010280 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010281 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010282
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010283 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010284 return 0;
10285
10286 pthread_mutex_lock(&adev_init_lock);
10287
10288 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010289 if (audio_extn_spkr_prot_is_enabled())
10290 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010291 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010292 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010293 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010294 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010295 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010296 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010297 audio_extn_utils_release_streams_cfg_lists(
10298 &adev->streams_output_cfg_list,
10299 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010300 if (audio_extn_qap_is_enabled())
10301 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010302 if (audio_extn_qaf_is_enabled())
10303 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010304 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010305 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010306 free(adev->snd_dev_ref_cnt);
10307 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010308 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10309 pcm_params_free(adev->use_case_table[i]);
10310 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010311 if (adev->adm_deinit)
10312 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010313 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010314 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010315 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010316 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010317 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010318 if (adev->device_cfg_params) {
10319 free(adev->device_cfg_params);
10320 adev->device_cfg_params = NULL;
10321 }
Derek Chend2530072014-11-24 12:39:14 -080010322 if(adev->ext_hw_plugin)
10323 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010324 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010325 free_map(adev->patch_map);
10326 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010327 free(device);
10328 adev = NULL;
10329 }
10330 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010331 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010332 return 0;
10333}
10334
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010335/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10336 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10337 * just that it _might_ work.
10338 */
10339static int period_size_is_plausible_for_low_latency(int period_size)
10340{
10341 switch (period_size) {
10342 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010343 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010344 case 240:
10345 case 320:
10346 case 480:
10347 return 1;
10348 default:
10349 return 0;
10350 }
10351}
10352
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010353static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10354{
10355 bool is_snd_card_status = false;
10356 bool is_ext_device_status = false;
10357 char value[32];
10358 int card = -1;
10359 card_status_t status;
10360
10361 if (cookie != adev || !parms)
10362 return;
10363
10364 if (!parse_snd_card_status(parms, &card, &status)) {
10365 is_snd_card_status = true;
10366 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10367 is_ext_device_status = true;
10368 } else {
10369 // not a valid event
10370 return;
10371 }
10372
10373 pthread_mutex_lock(&adev->lock);
10374 if (card == adev->snd_card || is_ext_device_status) {
10375 if (is_snd_card_status && adev->card_status != status) {
10376 adev->card_status = status;
10377 platform_snd_card_update(adev->platform, status);
10378 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010379 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010380 if (status == CARD_STATUS_OFFLINE)
10381 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010382 } else if (is_ext_device_status) {
10383 platform_set_parameters(adev->platform, parms);
10384 }
10385 }
10386 pthread_mutex_unlock(&adev->lock);
10387 return;
10388}
10389
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010390/* adev lock held */
10391int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010392{
10393 struct audio_usecase *uc_info;
Zhou Song3bbcee72020-12-27 19:13:04 +080010394 struct audio_usecase *usecase;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010395 struct listnode devices;
Zhou Song3bbcee72020-12-27 19:13:04 +080010396 struct listnode *node;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010397
10398 uc_info = get_usecase_from_list(adev, out->usecase);
10399 if (uc_info == NULL) {
10400 ALOGE("%s: Could not find the usecase (%d) in the list",
10401 __func__, out->usecase);
10402 return -EINVAL;
10403 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010404 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010405
Zhou Song1f93fa52020-11-20 13:57:39 +080010406 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10407 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010408
10409 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010410 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010411 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010412 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010413 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010414 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10415 select_devices(adev, uc_info->id);
Zhou Song1f93fa52020-11-20 13:57:39 +080010416
10417 if (is_offload_usecase(out->usecase)) {
10418 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010419 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Song1f93fa52020-11-20 13:57:39 +080010420 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10421 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10422 } else {
10423 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010424 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010425 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010426 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010427 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010428 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010429 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +080010430 // mute stream and switch to speaker if suspended
10431 if (!out->a2dp_muted && !out->standby) {
Zhou Song1f93fa52020-11-20 13:57:39 +080010432 assign_devices(&devices, &out->device_list);
10433 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Zhou Song3bbcee72020-12-27 19:13:04 +080010434 list_for_each(node, &adev->usecase_list) {
10435 usecase = node_to_item(node, struct audio_usecase, list);
10436 if ((usecase != uc_info) &&
10437 platform_check_backends_match(SND_DEVICE_OUT_SPEAKER,
10438 usecase->out_snd_device)) {
10439 assign_devices(&out->device_list, &usecase->stream.out->device_list);
10440 break;
10441 }
10442 }
Zhou Song5e44b782021-01-14 16:48:03 +080010443 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP) {
10444 out->a2dp_muted = true;
10445 if (is_offload_usecase(out->usecase)) {
10446 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10447 compress_pause(out->compr);
10448 out_set_compr_volume(&out->stream, (float)0, (float)0);
10449 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10450 out_set_voip_volume(&out->stream, (float)0, (float)0);
10451 } else {
10452 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10453 /* wait for stale pcm drained before switching to speaker */
10454 uint32_t latency =
10455 (out->config.period_count * out->config.period_size * 1000) /
10456 (out->config.rate);
10457 usleep(latency * 1000);
10458 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010459 }
10460 select_devices(adev, out->usecase);
Zhou Song5e44b782021-01-14 16:48:03 +080010461 ALOGD("%s: switched to device:%s and stream muted:%d", __func__,
10462 platform_get_snd_device_name(uc_info->out_snd_device), out->a2dp_muted);
Zhou Song1f93fa52020-11-20 13:57:39 +080010463 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010464 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10465 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010466 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010467 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010468 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010469 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010470 }
10471 ALOGV("%s: exit", __func__);
10472 return 0;
10473}
10474
Haynes Mathew George01156f92018-04-13 15:29:54 -070010475void adev_on_battery_status_changed(bool charging)
10476{
10477 pthread_mutex_lock(&adev->lock);
10478 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10479 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010480 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010481 pthread_mutex_unlock(&adev->lock);
10482}
10483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010484static int adev_open(const hw_module_t *module, const char *name,
10485 hw_device_t **device)
10486{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010487 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010488 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010489 char mixer_ctl_name[128] = {0};
10490 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010491
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010492 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010493 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10494
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010495 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010496 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010497 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010498 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010499 ALOGD("%s: returning existing instance of adev", __func__);
10500 ALOGD("%s: exit", __func__);
10501 pthread_mutex_unlock(&adev_init_lock);
10502 return 0;
10503 }
10504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010505 adev = calloc(1, sizeof(struct audio_device));
10506
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010507 if (!adev) {
10508 pthread_mutex_unlock(&adev_init_lock);
10509 return -ENOMEM;
10510 }
10511
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010512 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10513
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010514 // register audio ext hidl at the earliest
10515 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010516#ifdef DYNAMIC_LOG_ENABLED
10517 register_for_dynamic_logging("hal");
10518#endif
10519
Derek Chenf939fb72018-11-13 13:34:41 -080010520 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010521 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010522 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10523 maj_version = atoi(value);
10524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010525 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010526 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010527 adev->device.common.module = (struct hw_module_t *)module;
10528 adev->device.common.close = adev_close;
10529
10530 adev->device.init_check = adev_init_check;
10531 adev->device.set_voice_volume = adev_set_voice_volume;
10532 adev->device.set_master_volume = adev_set_master_volume;
10533 adev->device.get_master_volume = adev_get_master_volume;
10534 adev->device.set_master_mute = adev_set_master_mute;
10535 adev->device.get_master_mute = adev_get_master_mute;
10536 adev->device.set_mode = adev_set_mode;
10537 adev->device.set_mic_mute = adev_set_mic_mute;
10538 adev->device.get_mic_mute = adev_get_mic_mute;
10539 adev->device.set_parameters = adev_set_parameters;
10540 adev->device.get_parameters = adev_get_parameters;
10541 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10542 adev->device.open_output_stream = adev_open_output_stream;
10543 adev->device.close_output_stream = adev_close_output_stream;
10544 adev->device.open_input_stream = adev_open_input_stream;
10545 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010546 adev->device.create_audio_patch = adev_create_audio_patch;
10547 adev->device.release_audio_patch = adev_release_audio_patch;
10548 adev->device.get_audio_port = adev_get_audio_port;
10549 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010550 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010551 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010552
10553 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010554 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010555 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010556 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010557 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010558 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010559 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010560 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010561 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010562 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010563 /* Init audio and voice feature */
10564 audio_extn_feature_init();
10565 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010566 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010567 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010568 list_init(&adev->active_inputs_list);
10569 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010570 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010571 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10572 audio_extn_utils_hash_eq);
10573 if (!adev->io_streams_map) {
10574 ALOGE("%s: Could not create io streams map", __func__);
10575 ret = -ENOMEM;
10576 goto adev_open_err;
10577 }
10578 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10579 audio_extn_utils_hash_eq);
10580 if (!adev->patch_map) {
10581 ALOGE("%s: Could not create audio patch map", __func__);
10582 ret = -ENOMEM;
10583 goto adev_open_err;
10584 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010585 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010586 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010587 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010588 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010589 adev->perf_lock_opts[0] = 0x101;
10590 adev->perf_lock_opts[1] = 0x20E;
10591 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010592 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010593 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010594 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010595 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010596 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010597
Zhou Song68ebc352019-12-05 17:11:15 +080010598 audio_extn_perf_lock_init();
10599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010600 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010601 adev->platform = platform_init(adev);
10602 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010603 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010604 ret = -EINVAL;
10605 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010606 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010607
Aalique Grahame22e49102018-12-18 14:23:57 -080010608 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010609 if (audio_extn_qap_is_enabled()) {
10610 ret = audio_extn_qap_init(adev);
10611 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010612 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010613 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010614 }
10615 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10616 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10617 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010618
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010619 if (audio_extn_qaf_is_enabled()) {
10620 ret = audio_extn_qaf_init(adev);
10621 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010622 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010623 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010624 }
10625
10626 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10627 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10628 }
10629
Derek Chenae7b0342019-02-08 15:17:04 -080010630 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010631 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10632
Eric Laurentc4aef752013-09-12 17:45:53 -070010633 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10634 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10635 if (adev->visualizer_lib == NULL) {
10636 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10637 } else {
10638 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10639 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010640 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010641 "visualizer_hal_start_output");
10642 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010643 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010644 "visualizer_hal_stop_output");
10645 }
10646 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010647 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010648 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010649 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010650 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010651 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010652 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010653
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010654 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10655 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10656 if (adev->offload_effects_lib == NULL) {
10657 ALOGE("%s: DLOPEN failed for %s", __func__,
10658 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10659 } else {
10660 ALOGV("%s: DLOPEN successful for %s", __func__,
10661 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10662 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010663 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010664 "offload_effects_bundle_hal_start_output");
10665 adev->offload_effects_stop_output =
10666 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10667 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010668 adev->offload_effects_set_hpx_state =
10669 (int (*)(bool))dlsym(adev->offload_effects_lib,
10670 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010671 adev->offload_effects_get_parameters =
10672 (void (*)(struct str_parms *, struct str_parms *))
10673 dlsym(adev->offload_effects_lib,
10674 "offload_effects_bundle_get_parameters");
10675 adev->offload_effects_set_parameters =
10676 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10677 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010678 }
10679 }
10680
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010681 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10682 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10683 if (adev->adm_lib == NULL) {
10684 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10685 } else {
10686 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10687 adev->adm_init = (adm_init_t)
10688 dlsym(adev->adm_lib, "adm_init");
10689 adev->adm_deinit = (adm_deinit_t)
10690 dlsym(adev->adm_lib, "adm_deinit");
10691 adev->adm_register_input_stream = (adm_register_input_stream_t)
10692 dlsym(adev->adm_lib, "adm_register_input_stream");
10693 adev->adm_register_output_stream = (adm_register_output_stream_t)
10694 dlsym(adev->adm_lib, "adm_register_output_stream");
10695 adev->adm_deregister_stream = (adm_deregister_stream_t)
10696 dlsym(adev->adm_lib, "adm_deregister_stream");
10697 adev->adm_request_focus = (adm_request_focus_t)
10698 dlsym(adev->adm_lib, "adm_request_focus");
10699 adev->adm_abandon_focus = (adm_abandon_focus_t)
10700 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010701 adev->adm_set_config = (adm_set_config_t)
10702 dlsym(adev->adm_lib, "adm_set_config");
10703 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10704 dlsym(adev->adm_lib, "adm_request_focus_v2");
10705 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10706 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10707 adev->adm_on_routing_change = (adm_on_routing_change_t)
10708 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010709 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10710 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010711 }
10712 }
10713
Aalique Grahame22e49102018-12-18 14:23:57 -080010714 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010715 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010716 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010717 //initialize this to false for now,
10718 //this will be set to true through set param
10719 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010720
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010721 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010722 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010723
10724 if (k_enable_extended_precision)
10725 adev_verify_devices(adev);
10726
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010727 adev->dsp_bit_width_enforce_mode =
10728 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010729
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010730 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10731 &adev->streams_output_cfg_list,
10732 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010733
Kiran Kandi910e1862013-10-29 13:29:42 -070010734 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010735
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010736 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010737 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010738 trial = atoi(value);
10739 if (period_size_is_plausible_for_low_latency(trial)) {
10740 pcm_config_low_latency.period_size = trial;
10741 pcm_config_low_latency.start_threshold = trial / 4;
10742 pcm_config_low_latency.avail_min = trial / 4;
10743 configured_low_latency_capture_period_size = trial;
10744 }
10745 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010746 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10747 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010748 trial = atoi(value);
10749 if (period_size_is_plausible_for_low_latency(trial)) {
10750 configured_low_latency_capture_period_size = trial;
10751 }
10752 }
10753
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010754 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10755
Eric Laurent4b084132018-10-19 17:33:43 -070010756 adev->camera_orientation = CAMERA_DEFAULT;
10757
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010758 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010759 af_period_multiplier = atoi(value);
10760 if (af_period_multiplier < 0)
10761 af_period_multiplier = 2;
10762 else if (af_period_multiplier > 4)
10763 af_period_multiplier = 4;
10764
10765 ALOGV("new period_multiplier = %d", af_period_multiplier);
10766 }
10767
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010768 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010769
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010770 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010771 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010772 pthread_mutex_unlock(&adev_init_lock);
10773
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010774 if (adev->adm_init)
10775 adev->adm_data = adev->adm_init();
10776
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010777 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010778 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010779
10780 audio_extn_snd_mon_init();
10781 pthread_mutex_lock(&adev->lock);
10782 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10783 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010784 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10785 /*
10786 * if the battery state callback happens before charging can be queried,
10787 * it will be guarded with the adev->lock held in the cb function and so
10788 * the callback value will reflect the latest state
10789 */
10790 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010791 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010792 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010793 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010794 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010795 /* Allocate memory for Device config params */
10796 adev->device_cfg_params = (struct audio_device_config_param*)
10797 calloc(platform_get_max_codec_backend(),
10798 sizeof(struct audio_device_config_param));
10799 if (adev->device_cfg_params == NULL)
10800 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010801
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010802 /*
10803 * Check if new PSPD matrix mixer control is supported. If not
10804 * supported, then set flag so that old mixer ctrl is sent while
10805 * sending pspd coefficients on older kernel version. Query mixer
10806 * control for default pcm id and channel value one.
10807 */
10808 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10809 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10810
10811 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10812 if (!ctl) {
10813 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10814 __func__, mixer_ctl_name);
10815 adev->use_old_pspd_mix_ctrl = true;
10816 }
10817
Eric Laurent994a6932013-07-17 11:51:42 -070010818 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010819 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010820
10821adev_open_err:
10822 free_map(adev->patch_map);
10823 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010824 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010825 pthread_mutex_destroy(&adev->lock);
10826 free(adev);
10827 adev = NULL;
10828 *device = NULL;
10829 pthread_mutex_unlock(&adev_init_lock);
10830 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010831}
10832
10833static struct hw_module_methods_t hal_module_methods = {
10834 .open = adev_open,
10835};
10836
10837struct audio_module HAL_MODULE_INFO_SYM = {
10838 .common = {
10839 .tag = HARDWARE_MODULE_TAG,
10840 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10841 .hal_api_version = HARDWARE_HAL_API_VERSION,
10842 .id = AUDIO_HARDWARE_MODULE_ID,
10843 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010844 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010845 .methods = &hal_module_methods,
10846 },
10847};