blob: 5be3f4a36fd33f43e7fc202d9906266fc155e914 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shalini Manjunatha8ae54892020-12-29 13:02:25 +05302 * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
Xiaojun Sang782e5b12020-06-29 21:13:06 +080081
82#ifdef AUDIO_GKI_ENABLED
83#include "sound/audio_compressed_formats.h"
84#endif
85
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080087
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053088#ifdef DYNAMIC_LOG_ENABLED
89#include <log_xml_parser.h>
90#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
91#include <log_utils.h>
92#endif
93
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070094#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053095/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
96#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070098#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070099#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530100#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530101#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700102#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700103#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700104
Zhou Song1f93fa52020-11-20 13:57:39 +0800105#define PLAYBACK_GAIN_MAX 1.0f
Aalique Grahame22e49102018-12-18 14:23:57 -0800106#define RECORD_GAIN_MIN 0.0f
107#define RECORD_GAIN_MAX 1.0f
108#define RECORD_VOLUME_CTL_MAX 0x2000
109
110/* treat as unsigned Q1.13 */
111#define APP_TYPE_GAIN_DEFAULT 0x2000
112
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700113#define PROXY_OPEN_RETRY_COUNT 100
114#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800115
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800116#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
117 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
119#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
120 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800121
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700122#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700123#define DEFAULT_VOIP_BUF_DURATION_MS 20
124#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
125#define DEFAULT_VOIP_SAMP_RATE 48000
126
127#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
128
129struct pcm_config default_pcm_config_voip_copp = {
130 .channels = 1,
131 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
132 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
133 .period_count = 2,
134 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800135 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
136 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700137};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700138
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700139#define MIN_CHANNEL_COUNT 1
140#define DEFAULT_CHANNEL_COUNT 2
141#define MAX_HIFI_CHANNEL_COUNT 8
142
Aalique Grahame22e49102018-12-18 14:23:57 -0800143#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
144#define MAX_CHANNEL_COUNT 1
145#else
146#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
147#define XSTR(x) STR(x)
148#define STR(x) #x
149#endif
150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700151static unsigned int configured_low_latency_capture_period_size =
152 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
153
Haynes Mathew George16081042017-05-31 17:16:49 -0700154#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
155#define MMAP_PERIOD_COUNT_MIN 32
156#define MMAP_PERIOD_COUNT_MAX 512
157#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
158
Aalique Grahame22e49102018-12-18 14:23:57 -0800159/* This constant enables extended precision handling.
160 * TODO The flag is off until more testing is done.
161 */
162static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700163extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800164
Eric Laurentb23d5282013-05-14 15:27:20 -0700165struct pcm_config pcm_config_deep_buffer = {
166 .channels = 2,
167 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
168 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
169 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
170 .format = PCM_FORMAT_S16_LE,
171 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
172 .stop_threshold = INT_MAX,
173 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
174};
175
176struct pcm_config pcm_config_low_latency = {
177 .channels = 2,
178 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
179 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
180 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
183 .stop_threshold = INT_MAX,
184 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185};
186
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800187struct pcm_config pcm_config_haptics_audio = {
188 .channels = 1,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
191 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
194 .stop_threshold = INT_MAX,
195 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
196};
197
198struct pcm_config pcm_config_haptics = {
199 .channels = 1,
200 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
201 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
202 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
203 .format = PCM_FORMAT_S16_LE,
204 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
205 .stop_threshold = INT_MAX,
206 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209static int af_period_multiplier = 4;
210struct pcm_config pcm_config_rt = {
211 .channels = 2,
212 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
213 .period_size = ULL_PERIOD_SIZE, //1 ms
214 .period_count = 512, //=> buffer size is 512ms
215 .format = PCM_FORMAT_S16_LE,
216 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
217 .stop_threshold = INT_MAX,
218 .silence_threshold = 0,
219 .silence_size = 0,
220 .avail_min = ULL_PERIOD_SIZE, //1 ms
221};
222
Eric Laurentb23d5282013-05-14 15:27:20 -0700223struct pcm_config pcm_config_hdmi_multi = {
224 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
225 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
226 .period_size = HDMI_MULTI_PERIOD_SIZE,
227 .period_count = HDMI_MULTI_PERIOD_COUNT,
228 .format = PCM_FORMAT_S16_LE,
229 .start_threshold = 0,
230 .stop_threshold = INT_MAX,
231 .avail_min = 0,
232};
233
Haynes Mathew George16081042017-05-31 17:16:49 -0700234struct pcm_config pcm_config_mmap_playback = {
235 .channels = 2,
236 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
237 .period_size = MMAP_PERIOD_SIZE,
238 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
239 .format = PCM_FORMAT_S16_LE,
240 .start_threshold = MMAP_PERIOD_SIZE*8,
241 .stop_threshold = INT32_MAX,
242 .silence_threshold = 0,
243 .silence_size = 0,
244 .avail_min = MMAP_PERIOD_SIZE, //1 ms
245};
246
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700247struct pcm_config pcm_config_hifi = {
248 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
249 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
250 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
251 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
252 .format = PCM_FORMAT_S24_3LE,
253 .start_threshold = 0,
254 .stop_threshold = INT_MAX,
255 .avail_min = 0,
256};
257
Eric Laurentb23d5282013-05-14 15:27:20 -0700258struct pcm_config pcm_config_audio_capture = {
259 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
261 .format = PCM_FORMAT_S16_LE,
262};
263
Haynes Mathew George16081042017-05-31 17:16:49 -0700264struct pcm_config pcm_config_mmap_capture = {
265 .channels = 2,
266 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
267 .period_size = MMAP_PERIOD_SIZE,
268 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
269 .format = PCM_FORMAT_S16_LE,
270 .start_threshold = 0,
271 .stop_threshold = INT_MAX,
272 .silence_threshold = 0,
273 .silence_size = 0,
274 .avail_min = MMAP_PERIOD_SIZE, //1 ms
275};
276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700277#define AFE_PROXY_CHANNEL_COUNT 2
278#define AFE_PROXY_SAMPLING_RATE 48000
279
280#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
281#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
282
283struct pcm_config pcm_config_afe_proxy_playback = {
284 .channels = AFE_PROXY_CHANNEL_COUNT,
285 .rate = AFE_PROXY_SAMPLING_RATE,
286 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
287 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
288 .format = PCM_FORMAT_S16_LE,
289 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
290 .stop_threshold = INT_MAX,
291 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
292};
293
294#define AFE_PROXY_RECORD_PERIOD_SIZE 768
295#define AFE_PROXY_RECORD_PERIOD_COUNT 4
296
Aalique Grahame22e49102018-12-18 14:23:57 -0800297struct pcm_config pcm_config_audio_capture_rt = {
298 .channels = 2,
299 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
300 .period_size = ULL_PERIOD_SIZE,
301 .period_count = 512,
302 .format = PCM_FORMAT_S16_LE,
303 .start_threshold = 0,
304 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
305 .silence_threshold = 0,
306 .silence_size = 0,
307 .avail_min = ULL_PERIOD_SIZE, //1 ms
308};
309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700310struct pcm_config pcm_config_afe_proxy_record = {
311 .channels = AFE_PROXY_CHANNEL_COUNT,
312 .rate = AFE_PROXY_SAMPLING_RATE,
313 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
314 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
315 .format = PCM_FORMAT_S16_LE,
316 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
317 .stop_threshold = INT_MAX,
318 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
319};
320
Ashish Jainf1eaa582016-05-23 20:54:24 +0530321#define AUDIO_MAX_PCM_FORMATS 7
322
323const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
324 [AUDIO_FORMAT_DEFAULT] = 0,
325 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
326 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
327 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
328 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
329 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
330 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
331};
332
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800333const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700334 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
335 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800336 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800337 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700338 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
339 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700340 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700341 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
344 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
345 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
346 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
347 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
348 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
349 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700350 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
351 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700352 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800353 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700354
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700356 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530357 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
358 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
359 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530360 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
361 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700362 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700363 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700364 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700365 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700366
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800367 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800368 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400369 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
370 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700371
Derek Chenf7092792017-05-23 12:23:53 -0400372 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700373 [USECASE_VOICE2_CALL] = "voice2-call",
374 [USECASE_VOLTE_CALL] = "volte-call",
375 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800376 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800377 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
378 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800379 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700380 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
381 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
382 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800383 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
384 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
385 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
386
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700387 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
388 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700389 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
390 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700391
392 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
393 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800394 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530395 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700396
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530397 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530398 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
399 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700400
401 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
402 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530403 /* For Interactive Audio Streams */
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
406 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
407 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
408 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
409 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
410 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
411 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700412
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800413 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
414
Derek Chenf6318be2017-06-12 17:16:24 -0400415 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
416
417 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
418 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
419 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
420 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800421 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700422 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530423 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700424};
425
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426static const audio_usecase_t offload_usecases[] = {
427 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
430 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
431 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
432 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
433 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
434 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
435 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700436};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437
Varun Balaraje49253e2017-07-06 19:48:56 +0530438static const audio_usecase_t interactive_usecases[] = {
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
441 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
442 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
443 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
444 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
445 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
446 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
447};
448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449#define STRING_TO_ENUM(string) { #string, string }
450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451struct string_to_enum {
452 const char *name;
453 uint32_t value;
454};
455
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
460 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700461 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800462 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700465 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
466 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
467 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
470 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
471 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
472 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
473 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
474 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
475 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800476};
477
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700478static const struct string_to_enum formats_name_to_enum_table[] = {
479 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
480 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
481 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
483 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
484 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700485 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800486 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
487 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700488 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800489};
490
491//list of all supported sample rates by HDMI specification.
492static const int out_hdmi_sample_rates[] = {
493 32000, 44100, 48000, 88200, 96000, 176400, 192000,
494};
495
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700496static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800497 STRING_TO_ENUM(32000),
498 STRING_TO_ENUM(44100),
499 STRING_TO_ENUM(48000),
500 STRING_TO_ENUM(88200),
501 STRING_TO_ENUM(96000),
502 STRING_TO_ENUM(176400),
503 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800504 STRING_TO_ENUM(352800),
505 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700506};
507
Carter Hsu2e429db2019-05-14 18:50:52 +0800508struct in_effect_list {
509 struct listnode list;
510 effect_handle_t handle;
511};
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700514static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700515static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700516//cache last MBDRC cal step level
517static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530519static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700520static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800521static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530522static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530523
Derek Chen6f293672019-04-01 01:40:24 -0700524static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
525static void in_snd_mon_cb(void * stream, struct str_parms * parms);
526static void out_snd_mon_cb(void * stream, struct str_parms * parms);
527
Zhou Song331c8e52019-08-26 14:16:12 +0800528static int configure_btsco_sample_rate(snd_device_t snd_device);
529
Vatsal Buchac09ae062018-11-14 13:25:08 +0530530#ifdef AUDIO_FEATURE_ENABLED_GCOV
531extern void __gcov_flush();
532static void enable_gcov()
533{
534 __gcov_flush();
535}
536#else
537static void enable_gcov()
538{
539}
540#endif
541
justinweng20fb6d82019-02-21 18:49:00 -0700542static int in_set_microphone_direction(const struct audio_stream_in *stream,
543 audio_microphone_direction_t dir);
544static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
545
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700546static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
547 int flags __unused)
548{
549 int dir = 0;
550 switch (uc_id) {
551 case USECASE_AUDIO_RECORD_LOW_LATENCY:
552 dir = 1;
553 case USECASE_AUDIO_PLAYBACK_ULL:
554 break;
555 default:
556 return false;
557 }
558
559 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
560 PCM_PLAYBACK : PCM_CAPTURE);
561 if (adev->adm_is_noirq_avail)
562 return adev->adm_is_noirq_avail(adev->adm_data,
563 adev->snd_card, dev_id, dir);
564 return false;
565}
566
567static void register_out_stream(struct stream_out *out)
568{
569 struct audio_device *adev = out->dev;
570 if (is_offload_usecase(out->usecase) ||
571 !adev->adm_register_output_stream)
572 return;
573
574 // register stream first for backward compatibility
575 adev->adm_register_output_stream(adev->adm_data,
576 out->handle,
577 out->flags);
578
579 if (!adev->adm_set_config)
580 return;
581
582 if (out->realtime)
583 adev->adm_set_config(adev->adm_data,
584 out->handle,
585 out->pcm, &out->config);
586}
587
588static void register_in_stream(struct stream_in *in)
589{
590 struct audio_device *adev = in->dev;
591 if (!adev->adm_register_input_stream)
592 return;
593
594 adev->adm_register_input_stream(adev->adm_data,
595 in->capture_handle,
596 in->flags);
597
598 if (!adev->adm_set_config)
599 return;
600
601 if (in->realtime)
602 adev->adm_set_config(adev->adm_data,
603 in->capture_handle,
604 in->pcm,
605 &in->config);
606}
607
608static void request_out_focus(struct stream_out *out, long ns)
609{
610 struct audio_device *adev = out->dev;
611
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700612 if (adev->adm_request_focus_v2)
613 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
614 else if (adev->adm_request_focus)
615 adev->adm_request_focus(adev->adm_data, out->handle);
616}
617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619{
620 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700621 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623 if (adev->adm_request_focus_v2_1)
624 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
625 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
627 else if (adev->adm_request_focus)
628 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700629
630 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700631}
632
633static void release_out_focus(struct stream_out *out)
634{
635 struct audio_device *adev = out->dev;
636
637 if (adev->adm_abandon_focus)
638 adev->adm_abandon_focus(adev->adm_data, out->handle);
639}
640
641static void release_in_focus(struct stream_in *in)
642{
643 struct audio_device *adev = in->dev;
644 if (adev->adm_abandon_focus)
645 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
646}
647
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530648static int parse_snd_card_status(struct str_parms *parms, int *card,
649 card_status_t *status)
650{
651 char value[32]={0};
652 char state[32]={0};
653
654 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
655 if (ret < 0)
656 return -1;
657
658 // sscanf should be okay as value is of max length 32.
659 // same as sizeof state.
660 if (sscanf(value, "%d,%s", card, state) < 2)
661 return -1;
662
663 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
664 CARD_STATUS_OFFLINE;
665 return 0;
666}
667
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668static inline void adjust_frames_for_device_delay(struct stream_out *out,
669 uint32_t *dsp_frames) {
670 // Adjustment accounts for A2dp encoder latency with offload usecases
671 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800672 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700673 unsigned long offset =
674 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
675 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
676 }
677}
678
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700679static inline bool free_entry(void *key __unused,
680 void *value, void *context __unused)
681{
682 free(value);
683 return true;
684}
685
686static inline void free_map(Hashmap *map)
687{
688 if (map) {
689 hashmapForEach(map, free_entry, (void *) NULL);
690 hashmapFree(map);
691 }
692}
693
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800694static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 audio_patch_handle_t patch_handle)
696{
697 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
698 return;
699
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700 struct audio_patch_info *p_info =
701 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
702 if (p_info) {
703 ALOGV("%s: Remove patch %d", __func__, patch_handle);
704 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
705 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700706 free(p_info);
707 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700708}
709
710static inline int io_streams_map_insert(struct audio_device *adev,
711 struct audio_stream *stream,
712 audio_io_handle_t handle,
713 audio_patch_handle_t patch_handle)
714{
715 struct audio_stream_info *s_info =
716 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
717
718 if (s_info == NULL) {
719 ALOGE("%s: Could not allocate stream info", __func__);
720 return -ENOMEM;
721 }
722 s_info->stream = stream;
723 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724
725 pthread_mutex_lock(&adev->lock);
726 struct audio_stream_info *stream_info =
727 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700728 if (stream_info != NULL)
729 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800730 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700731 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
732 return 0;
733}
734
735static inline void io_streams_map_remove(struct audio_device *adev,
736 audio_io_handle_t handle)
737{
738 pthread_mutex_lock(&adev->lock);
739 struct audio_stream_info *s_info =
740 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700745 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746done:
747 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return;
749}
750
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800751static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 audio_patch_handle_t handle)
753{
754 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700755 p_info = (struct audio_patch_info *)
756 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700757 return p_info;
758}
759
vivek mehtaa76401a2015-04-24 14:12:15 -0700760__attribute__ ((visibility ("default")))
761bool audio_hw_send_gain_dep_calibration(int level) {
762 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700763 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700764
765 pthread_mutex_lock(&adev_init_lock);
766
767 if (adev != NULL && adev->platform != NULL) {
768 pthread_mutex_lock(&adev->lock);
769 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700770
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530771 // cache level info for any of the use case which
772 // was not started.
773 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700774
vivek mehtaa76401a2015-04-24 14:12:15 -0700775 pthread_mutex_unlock(&adev->lock);
776 } else {
777 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
778 }
779
780 pthread_mutex_unlock(&adev_init_lock);
781
782 return ret_val;
783}
784
Ashish Jain5106d362016-05-11 19:23:33 +0530785static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
786{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787 bool gapless_enabled = false;
788 const char *mixer_ctl_name = "Compress Gapless Playback";
789 struct mixer_ctl *ctl;
790
791 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700792 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530793
794 /*Disable gapless if its AV playback*/
795 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800796
797 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
798 if (!ctl) {
799 ALOGE("%s: Could not get ctl for mixer cmd - %s",
800 __func__, mixer_ctl_name);
801 return -EINVAL;
802 }
803
804 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
805 ALOGE("%s: Could not set gapless mode %d",
806 __func__, gapless_enabled);
807 return -EINVAL;
808 }
809 return 0;
810}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700811
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700812__attribute__ ((visibility ("default")))
813int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
814 int table_size) {
815 int ret_val = 0;
816 ALOGV("%s: enter ... ", __func__);
817
818 pthread_mutex_lock(&adev_init_lock);
819 if (adev == NULL) {
820 ALOGW("%s: adev is NULL .... ", __func__);
821 goto done;
822 }
823
824 pthread_mutex_lock(&adev->lock);
825 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
826 pthread_mutex_unlock(&adev->lock);
827done:
828 pthread_mutex_unlock(&adev_init_lock);
829 ALOGV("%s: exit ... ", __func__);
830 return ret_val;
831}
832
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800834{
835 bool ret = false;
836 ALOGV("%s: enter ...", __func__);
837
838 pthread_mutex_lock(&adev_init_lock);
839
840 if (adev != NULL && adev->platform != NULL) {
841 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800842 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800843 pthread_mutex_unlock(&adev->lock);
844 }
845
846 pthread_mutex_unlock(&adev_init_lock);
847
848 ALOGV("%s: exit with ret %d", __func__, ret);
849 return ret;
850}
Aalique Grahame22e49102018-12-18 14:23:57 -0800851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700852static bool is_supported_format(audio_format_t format)
853{
Eric Laurent86e17132013-09-12 17:49:30 -0700854 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530855 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530856 format == AUDIO_FORMAT_AAC_LC ||
857 format == AUDIO_FORMAT_AAC_HE_V1 ||
858 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530859 format == AUDIO_FORMAT_AAC_ADTS_LC ||
860 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
861 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530862 format == AUDIO_FORMAT_AAC_LATM_LC ||
863 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
864 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530865 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
866 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530867 format == AUDIO_FORMAT_PCM_FLOAT ||
868 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700869 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530870 format == AUDIO_FORMAT_AC3 ||
871 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700872 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530873 format == AUDIO_FORMAT_DTS ||
874 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530876 format == AUDIO_FORMAT_ALAC ||
877 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530878 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530879 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800880 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530881 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700882 format == AUDIO_FORMAT_APTX ||
883 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800884 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700885
886 return false;
887}
888
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700889static inline bool is_mmap_usecase(audio_usecase_t uc_id)
890{
891 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800892 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700893 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
894}
895
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700896static inline bool is_valid_volume(float left, float right)
897{
898 return ((left >= 0.0f && right >= 0.0f) ? true : false);
899}
900
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530901static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530902{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530903 ALOGV("%s", __func__);
904 audio_route_apply_and_update_path(adev->audio_route,
905 "asrc-mode");
906 adev->asrc_mode_enabled = true;
907}
908
909static void disable_asrc_mode(struct audio_device *adev)
910{
911 ALOGV("%s", __func__);
912 audio_route_reset_and_update_path(adev->audio_route,
913 "asrc-mode");
914 adev->asrc_mode_enabled = false;
915}
916
917/*
918 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
919 * 44.1 or Native DSD backends are enabled for any of current use case.
920 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
921 * - Disable current mix path use case(Headphone backend) and re-enable it with
922 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
923 * e.g. Naitve DSD or Headphone 44.1 -> + 48
924 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530925static void check_and_set_asrc_mode(struct audio_device *adev,
926 struct audio_usecase *uc_info,
927 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530928{
929 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530930 int i, num_new_devices = 0;
931 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
932 /*
933 *Split snd device for new combo use case
934 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
935 */
936 if (platform_split_snd_device(adev->platform,
937 snd_device,
938 &num_new_devices,
939 split_new_snd_devices) == 0) {
940 for (i = 0; i < num_new_devices; i++)
941 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
942 } else {
943 int new_backend_idx = platform_get_backend_index(snd_device);
944 if (((new_backend_idx == HEADPHONE_BACKEND) ||
945 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
946 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
947 !adev->asrc_mode_enabled) {
948 struct listnode *node = NULL;
949 struct audio_usecase *uc = NULL;
950 struct stream_out *curr_out = NULL;
951 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
952 int i, num_devices, ret = 0;
953 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530954
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530955 list_for_each(node, &adev->usecase_list) {
956 uc = node_to_item(node, struct audio_usecase, list);
957 curr_out = (struct stream_out*) uc->stream.out;
958 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
959 /*
960 *Split snd device for existing combo use case
961 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
962 */
963 ret = platform_split_snd_device(adev->platform,
964 uc->out_snd_device,
965 &num_devices,
966 split_snd_devices);
967 if (ret < 0 || num_devices == 0) {
968 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
969 split_snd_devices[0] = uc->out_snd_device;
970 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800971 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530972 for (i = 0; i < num_devices; i++) {
973 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
974 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
975 if((new_backend_idx == HEADPHONE_BACKEND) &&
976 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
977 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
978 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
979 __func__);
980 enable_asrc_mode(adev);
981 break;
982 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
983 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
984 (usecase_backend_idx == HEADPHONE_BACKEND)) {
985 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
986 __func__);
987 disable_audio_route(adev, uc);
988 disable_snd_device(adev, uc->out_snd_device);
989 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
990 if (new_backend_idx == DSD_NATIVE_BACKEND)
991 audio_route_apply_and_update_path(adev->audio_route,
992 "hph-true-highquality-mode");
993 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
994 (curr_out->bit_width >= 24))
995 audio_route_apply_and_update_path(adev->audio_route,
996 "hph-highquality-mode");
997 enable_asrc_mode(adev);
998 enable_snd_device(adev, uc->out_snd_device);
999 enable_audio_route(adev, uc);
1000 break;
1001 }
1002 }
1003 // reset split devices count
1004 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001005 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301006 if (adev->asrc_mode_enabled)
1007 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301008 }
1009 }
1010 }
1011}
1012
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001013static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1014 struct audio_effect_config effect_config,
1015 unsigned int param_value)
1016{
1017 char mixer_ctl_name[] = "Audio Effect";
1018 struct mixer_ctl *ctl;
1019 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001020 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001021
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001022 if (in == NULL) {
1023 ALOGE("%s: active input stream is NULL", __func__);
1024 return -EINVAL;
1025 }
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1028 if (!ctl) {
1029 ALOGE("%s: Could not get mixer ctl - %s",
1030 __func__, mixer_ctl_name);
1031 return -EINVAL;
1032 }
1033
1034 set_values[0] = 1; //0:Rx 1:Tx
1035 set_values[1] = in->app_type_cfg.app_type;
1036 set_values[2] = (long)effect_config.module_id;
1037 set_values[3] = (long)effect_config.instance_id;
1038 set_values[4] = (long)effect_config.param_id;
1039 set_values[5] = param_value;
1040
1041 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1042
1043 return 0;
1044
1045}
1046
1047static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1048 int effect_type, unsigned int *param_value)
1049{
1050 int ret = 0;
1051 struct audio_effect_config other_effect_config;
1052 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001053 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001054
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001055 if (in == NULL) {
1056 ALOGE("%s: active input stream is NULL", __func__);
1057 return -EINVAL;
1058 }
1059
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060 usecase = get_usecase_from_list(adev, in->usecase);
1061 if (!usecase)
1062 return -EINVAL;
1063
1064 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1065 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1066 if (ret < 0) {
1067 ALOGE("%s Failed to get effect params %d", __func__, ret);
1068 return ret;
1069 }
1070
1071 if (module_id == other_effect_config.module_id) {
1072 //Same module id for AEC/NS. Values need to be combined
1073 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1074 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1075 *param_value |= other_effect_config.param_value;
1076 }
1077 }
1078
1079 return ret;
1080}
1081
1082static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301083{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001084 struct audio_effect_config effect_config;
1085 struct audio_usecase *usecase = NULL;
1086 int ret = 0;
1087 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001088 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001089
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001090 if(!voice_extn_is_dynamic_ecns_enabled())
1091 return ENOSYS;
1092
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 if (!in) {
1094 ALOGE("%s: Invalid input stream", __func__);
1095 return -EINVAL;
1096 }
1097
1098 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1099
1100 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001101 if (usecase == NULL) {
1102 ALOGE("%s: Could not find the usecase (%d) in the list",
1103 __func__, in->usecase);
1104 return -EINVAL;
1105 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001106
1107 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1108 if (ret < 0) {
1109 ALOGE("%s Failed to get module id %d", __func__, ret);
1110 return ret;
1111 }
1112 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1113 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1114
1115 if(enable)
1116 param_value = effect_config.param_value;
1117
1118 /*Special handling for AEC & NS effects Param values need to be
1119 updated if module ids are same*/
1120
1121 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1122 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1123 if (ret < 0)
1124 return ret;
1125 }
1126
1127 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1128
1129 return ret;
1130}
1131
1132static void check_and_enable_effect(struct audio_device *adev)
1133{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001134 if(!voice_extn_is_dynamic_ecns_enabled())
1135 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001136
Eric Laurent637e2d42018-11-15 12:24:31 -08001137 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001138
Eric Laurent637e2d42018-11-15 12:24:31 -08001139 if (in != NULL && !in->standby) {
1140 if (in->enable_aec)
1141 enable_disable_effect(adev, EFFECT_AEC, true);
1142
1143 if (in->enable_ns &&
1144 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1145 enable_disable_effect(adev, EFFECT_NS, true);
1146 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147 }
1148}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001150int pcm_ioctl(struct pcm *pcm, int request, ...)
1151{
1152 va_list ap;
1153 void * arg;
1154 int pcm_fd = *(int*)pcm;
1155
1156 va_start(ap, request);
1157 arg = va_arg(ap, void *);
1158 va_end(ap);
1159
1160 return ioctl(pcm_fd, request, arg);
1161}
1162
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001163int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001164 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001167 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301168 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301169 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001170 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301171 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001172
1173 if (usecase == NULL)
1174 return -EINVAL;
1175
1176 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1177
Carter Hsu2e429db2019-05-14 18:50:52 +08001178 if (usecase->type == PCM_CAPTURE) {
1179 struct stream_in *in = usecase->stream.in;
1180 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001182
1183 if (in) {
1184 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001185 list_init(&out_devices);
1186 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 struct listnode *node;
1188 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1189 USECASE_AUDIO_PLAYBACK_VOIP);
1190 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001191 assign_devices(&out_devices,
1192 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001193 } else if (adev->primary_output &&
1194 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001195 assign_devices(&out_devices,
1196 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001197 } else {
1198 list_for_each(node, &adev->usecase_list) {
1199 uinfo = node_to_item(node, struct audio_usecase, list);
1200 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001201 assign_devices(&out_devices,
1202 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001203 break;
1204 }
1205 }
1206 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001207
1208 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001209 in->ec_opened = true;
1210 }
1211 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001212 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1213 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1214 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001215 snd_device = usecase->in_snd_device;
1216 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001219
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001220#ifdef DS1_DOLBY_DAP_ENABLED
1221 audio_extn_dolby_set_dmid(adev);
1222 audio_extn_dolby_set_endpoint(adev);
1223#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001224 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001225 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301226 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001227 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001228 if (audio_extn_is_maxx_audio_enabled())
1229 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301230 audio_extn_utils_send_audio_calibration(adev, usecase);
Zhou Song1f93fa52020-11-20 13:57:39 +08001231 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1232 out = usecase->stream.out;
1233 if (out && out->compr)
Manish Dewangan58229382017-02-02 15:48:41 +05301234 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1235 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301236
1237 if (usecase->type == PCM_CAPTURE) {
1238 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001239 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301240 ALOGD("%s: set custom mtmx params v1", __func__);
1241 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1242 }
1243 } else {
1244 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1245 }
Manish Dewangan58229382017-02-02 15:48:41 +05301246
Andy Hung756ecc12018-10-19 17:47:12 -07001247 // we shouldn't truncate mixer_path
1248 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1249 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1250 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001251 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001252 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301253 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1254 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1255 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1256 if (parms) {
1257 audio_extn_fm_set_parameters(adev, parms);
1258 str_parms_destroy(parms);
1259 }
1260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 ALOGV("%s: exit", __func__);
1262 return 0;
1263}
1264
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001265int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001266 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001268 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001269 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301270 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001271
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301272 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001273 return -EINVAL;
1274
1275 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301276 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device = usecase->in_snd_device;
1278 else
1279 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001280
1281 /* disable island and power mode on supported device for voice call */
1282 if (usecase->type == VOICE_CALL) {
1283 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1284 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1285 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1286 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1287 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1288 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1289 ALOGD("%s: disable island cfg and power mode in voice tx path",
1290 __func__);
1291 }
1292 }
1293 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1294 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1295 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1296 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1297 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1298 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1299 ALOGD("%s: disable island cfg and power mode in voice rx path",
1300 __func__);
1301 }
1302 }
1303 }
1304
Andy Hung756ecc12018-10-19 17:47:12 -07001305 // we shouldn't truncate mixer_path
1306 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1307 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1308 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001309 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001310 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001311 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001312 if (usecase->type == PCM_CAPTURE) {
1313 struct stream_in *in = usecase->stream.in;
1314 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001315 struct listnode out_devices;
1316 list_init(&out_devices);
1317 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001318 in->ec_opened = false;
1319 }
1320 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001321 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301322 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301323
1324 if (usecase->type == PCM_CAPTURE) {
1325 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001326 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327 ALOGD("%s: reset custom mtmx params v1", __func__);
1328 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1329 }
1330 } else {
1331 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1332 }
1333
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001334 if ((usecase->type == PCM_PLAYBACK) &&
1335 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301336 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001338 ALOGV("%s: exit", __func__);
1339 return 0;
1340}
1341
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001342int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001343 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301345 int i, num_devices = 0;
1346 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001347 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1348
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001349 if (snd_device < SND_DEVICE_MIN ||
1350 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001351 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001352 return -EINVAL;
1353 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001355 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001356 ALOGE("%s: Invalid sound device returned", __func__);
1357 return -EINVAL;
1358 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001359
1360 adev->snd_dev_ref_cnt[snd_device]++;
1361
1362 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1363 (platform_split_snd_device(adev->platform,
1364 snd_device,
1365 &num_devices,
1366 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001367 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001368 __func__, snd_device, device_name);
Aniket Kumar Latabce0be62019-07-11 14:20:23 -07001369 /* Set backend config for A2DP to ensure slimbus configuration
1370 is correct if A2DP is already active and backend is closed
1371 and re-opened */
1372 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
1373 audio_extn_a2dp_set_source_backend_cfg();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374 return 0;
1375 }
1376
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001377 if (audio_extn_spkr_prot_is_enabled())
1378 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001379
Aalique Grahame22e49102018-12-18 14:23:57 -08001380 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1381
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001382 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1383 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1385 goto err;
1386 }
1387 audio_extn_dev_arbi_acquire(snd_device);
1388 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001389 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001390 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001391 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001392 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001393 } else if (platform_split_snd_device(adev->platform,
1394 snd_device,
1395 &num_devices,
1396 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301397 for (i = 0; i < num_devices; i++) {
1398 enable_snd_device(adev, new_snd_devices[i]);
1399 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001400 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001402 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301403
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001404 /* enable island and power mode on supported device */
1405 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1406 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1407 platform_set_island_cfg_on_device(adev, snd_device, true);
1408 platform_set_power_mode_on_device(adev, snd_device, true);
1409 ALOGD("%s: enable island cfg and power mode on: %s",
1410 __func__, device_name);
1411 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301412
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301413 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1414 if (audio_extn_a2dp_start_playback() < 0) {
1415 ALOGE(" fail to configure A2dp Source control path ");
1416 goto err;
1417 } else {
1418 adev->a2dp_started = true;
1419 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001420 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001421
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1423 (audio_extn_a2dp_start_capture() < 0)) {
1424 ALOGE(" fail to configure A2dp Sink control path ");
1425 goto err;
1426 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301427
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001428 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1429 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1430 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1431 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1432 ALOGE(" fail to configure sco control path ");
1433 goto err;
1434 }
Zhou Song12c29502019-03-16 10:37:18 +08001435 }
1436
Zhou Song331c8e52019-08-26 14:16:12 +08001437 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001438 /* due to the possibility of calibration overwrite between listen
1439 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001440 audio_extn_sound_trigger_update_device_status(snd_device,
1441 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301442 audio_extn_listen_update_device_status(snd_device,
1443 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001444 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001445 audio_extn_sound_trigger_update_device_status(snd_device,
1446 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301447 audio_extn_listen_update_device_status(snd_device,
1448 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001449 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001450 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001451 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001452 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301453
1454 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1455 !adev->native_playback_enabled &&
1456 audio_is_true_native_stream_active(adev)) {
1457 ALOGD("%s: %d: napb: enabling native mode in hardware",
1458 __func__, __LINE__);
1459 audio_route_apply_and_update_path(adev->audio_route,
1460 "true-native-mode");
1461 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301462 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301463 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1464 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001465 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001466 ALOGD("%s: init ec ref loopback", __func__);
1467 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001471err:
1472 adev->snd_dev_ref_cnt[snd_device]--;
1473 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474}
1475
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001476int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001477 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301479 int i, num_devices = 0;
1480 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001483 if (snd_device < SND_DEVICE_MIN ||
1484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001486 return -EINVAL;
1487 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001488
1489 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1490 ALOGE("%s: Invalid sound device returned", __func__);
1491 return -EINVAL;
1492 }
1493
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1495 ALOGE("%s: device ref cnt is already 0", __func__);
1496 return -EINVAL;
1497 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001498
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001500
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001501
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001503 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301504
Aalique Grahame22e49102018-12-18 14:23:57 -08001505 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1506
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001507 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1508 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001509 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001510
1511 // when speaker device is disabled, reset swap.
1512 // will be renabled on usecase start
1513 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001514 } else if (platform_split_snd_device(adev->platform,
1515 snd_device,
1516 &num_devices,
1517 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301518 for (i = 0; i < num_devices; i++) {
1519 disable_snd_device(adev, new_snd_devices[i]);
1520 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001521 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001522 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001523 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001524 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001525
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301526 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301527 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301528 adev->a2dp_started = false;
1529 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001530 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001531 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301533 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301535 adev->native_playback_enabled) {
1536 ALOGD("%s: %d: napb: disabling native mode in hardware",
1537 __func__, __LINE__);
1538 audio_route_reset_and_update_path(adev->audio_route,
1539 "true-native-mode");
1540 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001541 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301542 adev->asrc_mode_enabled) {
1543 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301544 disable_asrc_mode(adev);
1545 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301547 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001548 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001549 ALOGD("%s: deinit ec ref loopback", __func__);
1550 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1551 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001552
1553 audio_extn_utils_release_snd_device(snd_device);
1554 } else {
1555 if (platform_split_snd_device(adev->platform,
1556 snd_device,
1557 &num_devices,
1558 new_snd_devices) == 0) {
1559 for (i = 0; i < num_devices; i++) {
1560 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1561 }
1562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 return 0;
1566}
1567
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001568/*
1569 legend:
1570 uc - existing usecase
1571 new_uc - new usecase
1572 d1, d11, d2 - SND_DEVICE enums
1573 a1, a2 - corresponding ANDROID device enums
1574 B1, B2 - backend strings
1575
1576case 1
1577 uc->dev d1 (a1) B1
1578 new_uc->dev d1 (a1), d2 (a2) B1, B2
1579
1580 resolution: disable and enable uc->dev on d1
1581
1582case 2
1583 uc->dev d1 (a1) B1
1584 new_uc->dev d11 (a1) B1
1585
1586 resolution: need to switch uc since d1 and d11 are related
1587 (e.g. speaker and voice-speaker)
1588 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1589
1590case 3
1591 uc->dev d1 (a1) B1
1592 new_uc->dev d2 (a2) B2
1593
1594 resolution: no need to switch uc
1595
1596case 4
1597 uc->dev d1 (a1) B1
1598 new_uc->dev d2 (a2) B1
1599
1600 resolution: disable enable uc-dev on d2 since backends match
1601 we cannot enable two streams on two different devices if they
1602 share the same backend. e.g. if offload is on speaker device using
1603 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1604 using the same backend, offload must also be switched to voice-handset.
1605
1606case 5
1607 uc->dev d1 (a1) B1
1608 new_uc->dev d1 (a1), d2 (a2) B1
1609
1610 resolution: disable enable uc-dev on d2 since backends match
1611 we cannot enable two streams on two different devices if they
1612 share the same backend.
1613
1614case 6
1615 uc->dev d1 (a1) B1
1616 new_uc->dev d2 (a1) B2
1617
1618 resolution: no need to switch
1619
1620case 7
1621 uc->dev d1 (a1), d2 (a2) B1, B2
1622 new_uc->dev d1 (a1) B1
1623
1624 resolution: no need to switch
1625
Zhou Song4ba65882018-07-09 14:48:07 +08001626case 8
1627 uc->dev d1 (a1) B1
1628 new_uc->dev d11 (a1), d2 (a2) B1, B2
1629 resolution: compared to case 1, for this case, d1 and d11 are related
1630 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301631
1632case 9
1633 uc->dev d1 (a1), d2(a2) B1 B2
1634 new_uc->dev d1 (a1), d22 (a2) B1, B2
1635 resolution: disable enable uc-dev on d2 since backends match
1636 we cannot enable two streams on two different devices if they
1637 share the same backend. This is special case for combo use case
1638 with a2dp and sco devices which uses same backend.
1639 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001640*/
1641static snd_device_t derive_playback_snd_device(void * platform,
1642 struct audio_usecase *uc,
1643 struct audio_usecase *new_uc,
1644 snd_device_t new_snd_device)
1645{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001646 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001647
1648 snd_device_t d1 = uc->out_snd_device;
1649 snd_device_t d2 = new_snd_device;
1650
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001651 list_init(&a1);
1652 list_init(&a2);
1653
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301654 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301655 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1657 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 break;
1659 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001660 assign_devices(&a1, &uc->stream.out->device_list);
1661 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301662 break;
1663 }
1664
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001665 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001666 if (!compare_devices(&a1, &a2) &&
1667 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001668 snd_device_t d3[2];
1669 int num_devices = 0;
1670 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001671 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001672 &num_devices,
1673 d3);
1674 if (ret < 0) {
1675 if (ret != -ENOSYS) {
1676 ALOGW("%s failed to split snd_device %d",
1677 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001678 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001679 }
1680 goto end;
1681 }
1682
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001683 if (platform_check_backends_match(d3[0], d3[1])) {
1684 return d2; // case 5
1685 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301686 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1687 platform_check_backends_match(d1, d2))
1688 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001689 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301690 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001691 // check if d1 is related to any of d3's
1692 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001693 return d1; // case 1
1694 else
1695 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001696 }
1697 } else {
1698 if (platform_check_backends_match(d1, d2)) {
1699 return d2; // case 2, 4
1700 } else {
1701 return d1; // case 6, 3
1702 }
1703 }
1704
1705end:
1706 return d2; // return whatever was calculated before.
1707}
1708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301710 struct audio_usecase *uc_info,
1711 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712{
1713 struct listnode *node;
1714 struct audio_usecase *usecase;
1715 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301716 snd_device_t uc_derive_snd_device;
1717 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001718 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1719 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001720 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301721 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001722 /*
1723 * This function is to make sure that all the usecases that are active on
1724 * the hardware codec backend are always routed to any one device that is
1725 * handled by the hardware codec.
1726 * For example, if low-latency and deep-buffer usecases are currently active
1727 * on speaker and out_set_parameters(headset) is received on low-latency
1728 * output, then we have to make sure deep-buffer is also switched to headset,
1729 * because of the limitation that both the devices cannot be enabled
1730 * at the same time as they share the same backend.
1731 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001732 /*
1733 * This call is to check if we need to force routing for a particular stream
1734 * If there is a backend configuration change for the device when a
1735 * new stream starts, then ADM needs to be closed and re-opened with the new
1736 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001737 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001738 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001739 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1740 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301741 /* For a2dp device reconfigure all active sessions
1742 * with new AFE encoder format based on a2dp state
1743 */
1744 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301745 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1746 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301747 audio_extn_a2dp_is_force_device_switch()) {
1748 force_routing = true;
1749 force_restart_session = true;
1750 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001751
1752 /*
1753 * Island cfg and power mode config needs to set before AFE port start.
1754 * Set force routing in case of voice device was enable before.
1755 */
1756 if (uc_info->type == VOICE_CALL &&
1757 voice_extn_is_voice_power_mode_supported() &&
1758 platform_check_and_update_island_power_status(adev->platform,
1759 uc_info,
1760 snd_device)) {
1761 force_routing = true;
1762 ALOGD("%s:becf: force routing %d for power mode supported device",
1763 __func__, force_routing);
1764 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301765 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1766
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001768 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001769 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1771 switch_device[i] = false;
1772
1773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001775
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301776 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1777 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301778 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301779 platform_get_snd_device_name(usecase->out_snd_device),
1780 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301781 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1782 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301783 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1784 usecase, uc_info, snd_device);
1785 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001786 (is_codec_backend_out_device_type(&usecase->device_list) ||
1787 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1788 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1789 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1790 is_a2dp_out_device_type(&usecase->device_list) ||
1791 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301792 ((force_restart_session) ||
1793 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301794 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1795 __func__, use_case_table[usecase->id],
1796 platform_get_snd_device_name(usecase->out_snd_device));
1797 disable_audio_route(adev, usecase);
1798 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301799 /* Enable existing usecase on derived playback device */
1800 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301801 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301802 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803 }
1804 }
1805
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301806 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1807 num_uc_to_switch);
1808
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001809 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001810 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301812 /* Make sure the previous devices to be disabled first and then enable the
1813 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 list_for_each(node, &adev->usecase_list) {
1815 usecase = node_to_item(node, struct audio_usecase, list);
1816 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001817 /* Check if output sound device to be switched can be split and if any
1818 of the split devices match with derived sound device */
1819 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1820 &num_devices, split_snd_devices) == 0) {
1821 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1822 for (i = 0; i < num_devices; i++) {
1823 /* Disable devices that do not match with derived sound device */
1824 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1825 disable_snd_device(adev, split_snd_devices[i]);
1826 }
1827 } else {
1828 disable_snd_device(adev, usecase->out_snd_device);
1829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 }
1831 }
1832
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001833 list_for_each(node, &adev->usecase_list) {
1834 usecase = node_to_item(node, struct audio_usecase, list);
1835 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001836 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1837 &num_devices, split_snd_devices) == 0) {
1838 /* Enable derived sound device only if it does not match with
1839 one of the split sound devices. This is because the matching
1840 sound device was not disabled */
1841 bool should_enable = true;
1842 for (i = 0; i < num_devices; i++) {
1843 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1844 should_enable = false;
1845 break;
1846 }
1847 }
1848 if (should_enable)
1849 enable_snd_device(adev, derive_snd_device[usecase->id]);
1850 } else {
1851 enable_snd_device(adev, derive_snd_device[usecase->id]);
1852 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001853 }
1854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 /* Re-route all the usecases on the shared backend other than the
1857 specified usecase to new snd devices */
1858 list_for_each(node, &adev->usecase_list) {
1859 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301860 /* Update the out_snd_device only before enabling the audio route */
1861 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301862 usecase->out_snd_device = derive_snd_device[usecase->id];
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301863 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
1864 use_case_table[usecase->id],
1865 platform_get_snd_device_name(usecase->out_snd_device));
1866 /* Update voc calibration before enabling Voice/VoIP route */
1867 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
1868 status = platform_switch_voice_call_device_post(adev->platform,
1869 usecase->out_snd_device,
1870 platform_get_input_snd_device(
1871 adev->platform, NULL,
1872 &uc_info->device_list,
1873 usecase->type));
1874 enable_audio_route(adev, usecase);
1875 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1876 out_set_voip_volume(&usecase->stream.out->stream,
1877 usecase->stream.out->volume_l,
1878 usecase->stream.out->volume_r);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880 }
1881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 }
1883}
1884
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301885static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001886 struct audio_usecase *uc_info,
1887 snd_device_t snd_device)
1888{
1889 struct listnode *node;
1890 struct audio_usecase *usecase;
1891 bool switch_device[AUDIO_USECASE_MAX];
1892 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001893 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001894 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001895
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301896 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1897 snd_device);
1898 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301899
1900 /*
1901 * Make sure out devices is checked against out codec backend device and
1902 * also in devices against in codec backend. Checking out device against in
1903 * codec backend or vice versa causes issues.
1904 */
1905 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001906 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001907
1908 /*
1909 * Island cfg and power mode config needs to set before AFE port start.
1910 * Set force routing in case of voice device was enable before.
1911 */
1912
1913 if (uc_info->type == VOICE_CALL &&
1914 voice_extn_is_voice_power_mode_supported() &&
1915 platform_check_and_update_island_power_status(adev->platform,
1916 uc_info,
1917 snd_device)) {
1918 force_routing = true;
1919 ALOGD("%s:becf: force routing %d for power mode supported device",
1920 __func__, force_routing);
1921 }
1922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 /*
1924 * This function is to make sure that all the active capture usecases
1925 * are always routed to the same input sound device.
1926 * For example, if audio-record and voice-call usecases are currently
1927 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1928 * is received for voice call then we have to make sure that audio-record
1929 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1930 * because of the limitation that two devices cannot be enabled
1931 * at the same time if they share the same backend.
1932 */
1933 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1934 switch_device[i] = false;
1935
1936 list_for_each(node, &adev->usecase_list) {
1937 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301938 /*
1939 * TODO: Enhance below condition to handle BT sco/USB multi recording
1940 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301941
1942 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1943 (usecase->in_snd_device != snd_device || force_routing));
1944 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1945 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1946 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001947 ((backend_check_cond &&
1948 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001949 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001950 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001951 is_single_device_type_equal(&usecase->device_list,
1952 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001953 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001954 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001955 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301956 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001957 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001958 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001959 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001960 switch_device[usecase->id] = true;
1961 num_uc_to_switch++;
1962 }
1963 }
1964
1965 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001966 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001967
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301968 /* Make sure the previous devices to be disabled first and then enable the
1969 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001970 list_for_each(node, &adev->usecase_list) {
1971 usecase = node_to_item(node, struct audio_usecase, list);
1972 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001973 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001974 }
1975 }
1976
1977 list_for_each(node, &adev->usecase_list) {
1978 usecase = node_to_item(node, struct audio_usecase, list);
1979 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001981 }
1982 }
1983
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001984 /* Re-route all the usecases on the shared backend other than the
1985 specified usecase to new snd devices */
1986 list_for_each(node, &adev->usecase_list) {
1987 usecase = node_to_item(node, struct audio_usecase, list);
1988 /* Update the in_snd_device only before enabling the audio route */
1989 if (switch_device[usecase->id] ) {
1990 usecase->in_snd_device = snd_device;
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05301991 /* Update voc calibration before enabling Voice/VoIP route */
1992 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1993 snd_device_t voip_snd_device;
1994 voip_snd_device = platform_get_output_snd_device(adev->platform,
1995 usecase->stream.out,
1996 usecase->type);
1997 status = platform_switch_voice_call_device_post(adev->platform,
1998 voip_snd_device,
1999 usecase->in_snd_device);
kunleiz5cd52b82016-11-07 17:22:52 +08002000 }
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302001 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002002 }
2003 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002004 }
2005}
2006
Mingming Yin3a941d42016-02-17 18:08:05 -08002007static void reset_hdmi_sink_caps(struct stream_out *out) {
2008 int i = 0;
2009
2010 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2011 out->supported_channel_masks[i] = 0;
2012 }
2013 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2014 out->supported_formats[i] = 0;
2015 }
2016 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2017 out->supported_sample_rates[i] = 0;
2018 }
2019}
2020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002022static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023{
Mingming Yin3a941d42016-02-17 18:08:05 -08002024 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002025 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2026 out->extconn.cs.controller,
2027 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028
Mingming Yin3a941d42016-02-17 18:08:05 -08002029 reset_hdmi_sink_caps(out);
2030
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002031 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002032 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002033 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002034 out->extconn.cs.stream);
2035 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002036 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002037 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002038 }
2039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002042 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002043 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002044 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2045 case 6:
2046 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2047 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2048 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2049 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2050 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2051 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 break;
2053 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002054 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002055 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 break;
2057 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002058
2059 // check channel format caps
2060 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002061 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2062 out->extconn.cs.controller,
2063 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002064 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2065 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2066 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2067 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2068 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2069 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2070 }
2071
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002072 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2073 out->extconn.cs.controller,
2074 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002075 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2076 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2077 }
2078
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002079 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2080 out->extconn.cs.controller,
2081 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002082 ALOGV(":%s HDMI supports DTS format", __func__);
2083 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2084 }
2085
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002086 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2087 out->extconn.cs.controller,
2088 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002089 ALOGV(":%s HDMI supports DTS HD format", __func__);
2090 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2091 }
2092
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002093 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2094 out->extconn.cs.controller,
2095 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002096 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2097 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2098 }
2099
Mingming Yin3a941d42016-02-17 18:08:05 -08002100
2101 // check sample rate caps
2102 i = 0;
2103 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002104 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2105 out->extconn.cs.controller,
2106 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002107 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2108 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2109 }
2110 }
2111
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002112 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113}
2114
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002115static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2116 uint32_t *supported_sample_rates __unused,
2117 uint32_t max_rates __unused)
2118{
2119 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2120 supported_sample_rates,
2121 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302122 ssize_t i = 0;
2123
2124 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002125 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2126 supported_sample_rates[i]);
2127 }
2128 return count;
2129}
2130
2131static inline int read_usb_sup_channel_masks(bool is_playback,
2132 audio_channel_mask_t *supported_channel_masks,
2133 uint32_t max_masks)
2134{
2135 int channels = audio_extn_usb_get_max_channels(is_playback);
2136 int channel_count;
2137 uint32_t num_masks = 0;
2138 if (channels > MAX_HIFI_CHANNEL_COUNT)
2139 channels = MAX_HIFI_CHANNEL_COUNT;
2140
2141 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002142 // start from 2 channels as framework currently doesn't support mono.
2143 if (channels >= FCC_2) {
2144 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2145 }
2146 for (channel_count = FCC_2;
2147 channel_count <= channels && num_masks < max_masks;
2148 ++channel_count) {
2149 supported_channel_masks[num_masks++] =
2150 audio_channel_mask_for_index_assignment_from_count(channel_count);
2151 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002152 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002153 // For capture we report all supported channel masks from 1 channel up.
2154 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002155 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2156 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002157 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2158 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2159 if (channel_count <= FCC_2) {
2160 mask = audio_channel_in_mask_from_count(channel_count);
2161 supported_channel_masks[num_masks++] = mask;
2162 }
2163 const audio_channel_mask_t index_mask =
2164 audio_channel_mask_for_index_assignment_from_count(channel_count);
2165 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2166 supported_channel_masks[num_masks++] = index_mask;
2167 }
2168 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002169 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302170
vincenttewf51c94e2019-05-07 10:28:53 +08002171 for (size_t i = 0; i < num_masks; ++i) {
2172 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2173 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302174 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002175 return num_masks;
2176}
2177
2178static inline int read_usb_sup_formats(bool is_playback __unused,
2179 audio_format_t *supported_formats,
2180 uint32_t max_formats __unused)
2181{
2182 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2183 switch (bitwidth) {
2184 case 24:
2185 // XXX : usb.c returns 24 for s24 and s24_le?
2186 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2187 break;
2188 case 32:
2189 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2190 break;
2191 case 16:
2192 default :
2193 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2194 break;
2195 }
2196 ALOGV("%s: %s supported format %d", __func__,
2197 is_playback ? "P" : "C", bitwidth);
2198 return 1;
2199}
2200
2201static inline int read_usb_sup_params_and_compare(bool is_playback,
2202 audio_format_t *format,
2203 audio_format_t *supported_formats,
2204 uint32_t max_formats,
2205 audio_channel_mask_t *mask,
2206 audio_channel_mask_t *supported_channel_masks,
2207 uint32_t max_masks,
2208 uint32_t *rate,
2209 uint32_t *supported_sample_rates,
2210 uint32_t max_rates) {
2211 int ret = 0;
2212 int num_formats;
2213 int num_masks;
2214 int num_rates;
2215 int i;
2216
2217 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2218 max_formats);
2219 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2220 max_masks);
2221
2222 num_rates = read_usb_sup_sample_rates(is_playback,
2223 supported_sample_rates, max_rates);
2224
2225#define LUT(table, len, what, dflt) \
2226 for (i=0; i<len && (table[i] != what); i++); \
2227 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2228
2229 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2230 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2231 LUT(supported_sample_rates, num_rates, *rate, 0);
2232
2233#undef LUT
2234 return ret < 0 ? -EINVAL : 0; // HACK TBD
2235}
2236
Alexy Josephb1379942016-01-29 15:49:38 -08002237audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002238 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002239{
2240 struct audio_usecase *usecase;
2241 struct listnode *node;
2242
2243 list_for_each(node, &adev->usecase_list) {
2244 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002245 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002246 ALOGV("%s: usecase id %d", __func__, usecase->id);
2247 return usecase->id;
2248 }
2249 }
2250 return USECASE_INVALID;
2251}
2252
Alexy Josephb1379942016-01-29 15:49:38 -08002253struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002254 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255{
2256 struct audio_usecase *usecase;
2257 struct listnode *node;
2258
2259 list_for_each(node, &adev->usecase_list) {
2260 usecase = node_to_item(node, struct audio_usecase, list);
2261 if (usecase->id == uc_id)
2262 return usecase;
2263 }
2264 return NULL;
2265}
2266
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302267/*
2268 * is a true native playback active
2269 */
2270bool audio_is_true_native_stream_active(struct audio_device *adev)
2271{
2272 bool active = false;
2273 int i = 0;
2274 struct listnode *node;
2275
2276 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2277 ALOGV("%s:napb: not in true mode or non hdphones device",
2278 __func__);
2279 active = false;
2280 goto exit;
2281 }
2282
2283 list_for_each(node, &adev->usecase_list) {
2284 struct audio_usecase *uc;
2285 uc = node_to_item(node, struct audio_usecase, list);
2286 struct stream_out *curr_out =
2287 (struct stream_out*) uc->stream.out;
2288
2289 if (curr_out && PCM_PLAYBACK == uc->type) {
2290 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2291 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2292 uc->id, curr_out->sample_rate,
2293 curr_out->bit_width,
2294 platform_get_snd_device_name(uc->out_snd_device));
2295
2296 if (is_offload_usecase(uc->id) &&
2297 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2298 active = true;
2299 ALOGD("%s:napb:native stream detected", __func__);
2300 }
2301 }
2302 }
2303exit:
2304 return active;
2305}
2306
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002307uint32_t adev_get_dsp_bit_width_enforce_mode()
2308{
2309 if (adev == NULL) {
2310 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2311 return 0;
2312 }
2313 return adev->dsp_bit_width_enforce_mode;
2314}
2315
2316static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2317{
2318 char value[PROPERTY_VALUE_MAX];
2319 int trial;
2320 uint32_t dsp_bit_width_enforce_mode = 0;
2321
2322 if (!mixer) {
2323 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2324 __func__);
2325 return 0;
2326 }
2327
2328 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2329 value, NULL) > 0) {
2330 trial = atoi(value);
2331 switch (trial) {
2332 case 16:
2333 dsp_bit_width_enforce_mode = 16;
2334 break;
2335 case 24:
2336 dsp_bit_width_enforce_mode = 24;
2337 break;
2338 case 32:
2339 dsp_bit_width_enforce_mode = 32;
2340 break;
2341 default:
2342 dsp_bit_width_enforce_mode = 0;
2343 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2344 break;
2345 }
2346 }
2347
2348 return dsp_bit_width_enforce_mode;
2349}
2350
2351static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2352 uint32_t enforce_mode,
2353 bool enable)
2354{
2355 struct mixer_ctl *ctl = NULL;
2356 const char *mixer_ctl_name = "ASM Bit Width";
2357 uint32_t asm_bit_width_mode = 0;
2358
2359 if (enforce_mode == 0) {
2360 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2361 return;
2362 }
2363
2364 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2365 if (!ctl) {
2366 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2367 __func__, mixer_ctl_name);
2368 return;
2369 }
2370
2371 if (enable)
2372 asm_bit_width_mode = enforce_mode;
2373 else
2374 asm_bit_width_mode = 0;
2375
2376 ALOGV("%s DSP bit width feature status is %d width=%d",
2377 __func__, enable, asm_bit_width_mode);
2378 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2379 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2380 asm_bit_width_mode);
2381
2382 return;
2383}
2384
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302385/*
2386 * if native DSD playback active
2387 */
2388bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2389{
2390 bool active = false;
2391 struct listnode *node = NULL;
2392 struct audio_usecase *uc = NULL;
2393 struct stream_out *curr_out = NULL;
2394
2395 list_for_each(node, &adev->usecase_list) {
2396 uc = node_to_item(node, struct audio_usecase, list);
2397 curr_out = (struct stream_out*) uc->stream.out;
2398
2399 if (curr_out && PCM_PLAYBACK == uc->type &&
2400 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2401 active = true;
2402 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302403 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302404 }
2405 }
2406 return active;
2407}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302408
2409static bool force_device_switch(struct audio_usecase *usecase)
2410{
2411 bool ret = false;
2412 bool is_it_true_mode = false;
2413
Zhou Song30f2c3e2018-02-08 14:02:15 +08002414 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302415 usecase->type == TRANSCODE_LOOPBACK_RX ||
2416 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002417 return false;
2418 }
2419
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002420 if(usecase->stream.out == NULL) {
2421 ALOGE("%s: stream.out is NULL", __func__);
2422 return false;
2423 }
2424
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302425 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002426 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002427 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2428 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302429 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2430 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2431 (!is_it_true_mode && adev->native_playback_enabled)){
2432 ret = true;
2433 ALOGD("napb: time to toggle native mode");
2434 }
2435 }
2436
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302437 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302438 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2439 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002440 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302441 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302442 ALOGD("Force a2dp device switch to update new encoder config");
2443 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002444 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302445
Florian Pfister1a84f312018-07-19 14:38:18 +02002446 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302447 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2448 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002449 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302450 return ret;
2451}
2452
Aalique Grahame22e49102018-12-18 14:23:57 -08002453static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2454{
2455 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2456}
2457
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302458bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2459{
2460 bool ret=false;
2461 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002462 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2463 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302464 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2465 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002466 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002468 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2469 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302470 ret = true;
2471
2472 return ret;
2473}
2474
2475bool is_a2dp_device(snd_device_t out_snd_device)
2476{
2477 bool ret=false;
2478 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2479 ret = true;
2480
2481 return ret;
2482}
2483
2484bool is_bt_soc_on(struct audio_device *adev)
2485{
2486 struct mixer_ctl *ctl;
2487 char *mixer_ctl_name = "BT SOC status";
2488 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2489 bool bt_soc_status = true;
2490 if (!ctl) {
2491 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2492 __func__, mixer_ctl_name);
2493 /*This is to ensure we dont break targets which dont have the kernel change*/
2494 return true;
2495 }
2496 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2497 ALOGD("BT SOC status: %d",bt_soc_status);
2498 return bt_soc_status;
2499}
2500
Zhou Song331c8e52019-08-26 14:16:12 +08002501static int configure_btsco_sample_rate(snd_device_t snd_device)
2502{
2503 struct mixer_ctl *ctl = NULL;
2504 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2505 char *rate_str = NULL;
2506 bool is_rx_dev = true;
2507
2508 if (is_btsco_device(snd_device, snd_device)) {
2509 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2510 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2511 if (!ctl_sr_tx || !ctl_sr_rx) {
2512 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2513 if (!ctl_sr)
2514 return -ENOSYS;
2515 }
2516
2517 switch (snd_device) {
2518 case SND_DEVICE_OUT_BT_SCO:
2519 rate_str = "KHZ_8";
2520 break;
2521 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2522 case SND_DEVICE_IN_BT_SCO_MIC:
2523 rate_str = "KHZ_8";
2524 is_rx_dev = false;
2525 break;
2526 case SND_DEVICE_OUT_BT_SCO_WB:
2527 rate_str = "KHZ_16";
2528 break;
2529 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2530 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2531 rate_str = "KHZ_16";
2532 is_rx_dev = false;
2533 break;
2534 default:
2535 return 0;
2536 }
2537
2538 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2539 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2540 return -ENOSYS;
2541 }
2542 return 0;
2543}
2544
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302545int out_standby_l(struct audio_stream *stream);
2546
Eric Laurent637e2d42018-11-15 12:24:31 -08002547struct stream_in *adev_get_active_input(const struct audio_device *adev)
2548{
2549 struct listnode *node;
2550 struct stream_in *last_active_in = NULL;
2551
2552 /* Get last added active input.
2553 * TODO: We may use a priority mechanism to pick highest priority active source */
2554 list_for_each(node, &adev->usecase_list)
2555 {
2556 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2557 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2558 last_active_in = usecase->stream.in;
2559 }
2560
2561 return last_active_in;
2562}
2563
2564struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2565{
2566 struct listnode *node;
2567
2568 /* First check active inputs with voice communication source and then
2569 * any input if audio mode is in communication */
2570 list_for_each(node, &adev->usecase_list)
2571 {
2572 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2573 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2574 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2575 return usecase->stream.in;
2576 }
2577 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2578 return adev_get_active_input(adev);
2579
2580 return NULL;
2581}
2582
Carter Hsu2e429db2019-05-14 18:50:52 +08002583/*
2584 * Aligned with policy.h
2585 */
2586static inline int source_priority(int inputSource)
2587{
2588 switch (inputSource) {
2589 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2590 return 9;
2591 case AUDIO_SOURCE_CAMCORDER:
2592 return 8;
2593 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2594 return 7;
2595 case AUDIO_SOURCE_UNPROCESSED:
2596 return 6;
2597 case AUDIO_SOURCE_MIC:
2598 return 5;
2599 case AUDIO_SOURCE_ECHO_REFERENCE:
2600 return 4;
2601 case AUDIO_SOURCE_FM_TUNER:
2602 return 3;
2603 case AUDIO_SOURCE_VOICE_RECOGNITION:
2604 return 2;
2605 case AUDIO_SOURCE_HOTWORD:
2606 return 1;
2607 default:
2608 break;
2609 }
2610 return 0;
2611}
2612
2613static struct stream_in *get_priority_input(struct audio_device *adev)
2614{
2615 struct listnode *node;
2616 struct audio_usecase *usecase;
2617 int last_priority = 0, priority;
2618 struct stream_in *priority_in = NULL;
2619 struct stream_in *in;
2620
2621 list_for_each(node, &adev->usecase_list) {
2622 usecase = node_to_item(node, struct audio_usecase, list);
2623 if (usecase->type == PCM_CAPTURE) {
2624 in = usecase->stream.in;
2625 if (!in)
2626 continue;
2627 priority = source_priority(in->source);
2628
2629 if (priority > last_priority) {
2630 last_priority = priority;
2631 priority_in = in;
2632 }
2633 }
2634 }
2635 return priority_in;
2636}
2637
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002638int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002640 snd_device_t out_snd_device = SND_DEVICE_NONE;
2641 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642 struct audio_usecase *usecase = NULL;
2643 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002644 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002645 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302646 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002647 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002648 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302650 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002652 usecase = get_usecase_from_list(adev, uc_id);
2653 if (usecase == NULL) {
2654 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2655 return -EINVAL;
2656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002658 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002659 (usecase->type == VOIP_CALL) ||
2660 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302661 if(usecase->stream.out == NULL) {
2662 ALOGE("%s: stream.out is NULL", __func__);
2663 return -EINVAL;
2664 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002665 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002666 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2667 uc_id);
2668 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2669 uc_id);
2670 } else {
2671 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302672 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002673 in_snd_device = platform_get_input_snd_device(adev->platform,
2674 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302675 &usecase->stream.out->device_list,
2676 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002677 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002678 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302679 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302680 if (usecase->stream.inout == NULL) {
2681 ALOGE("%s: stream.inout is NULL", __func__);
2682 return -EINVAL;
2683 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002684 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302685 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2686 stream_out.format = usecase->stream.inout->out_config.format;
2687 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302688 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002689 assign_devices(&usecase->device_list,
2690 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302691 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2692 if (usecase->stream.inout == NULL) {
2693 ALOGE("%s: stream.inout is NULL", __func__);
2694 return -EINVAL;
2695 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302696 struct listnode out_devices;
2697 list_init(&out_devices);
2698 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2699 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002700 assign_devices(&usecase->device_list,
2701 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 } else {
2703 /*
2704 * If the voice call is active, use the sound devices of voice call usecase
2705 * so that it would not result any device switch. All the usecases will
2706 * be switched to new device when select_devices() is called for voice call
2707 * usecase. This is to avoid switching devices for voice call when
2708 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002709 * choose voice call device only if the use case device is
2710 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002712 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002713 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002714 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002715 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2716 is_codec_backend_out_device_type(&usecase->device_list)) ||
2717 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2718 is_codec_backend_in_device_type(&usecase->device_list)) ||
2719 is_single_device_type_equal(&vc_usecase->device_list,
2720 AUDIO_DEVICE_OUT_HEARING_AID) ||
2721 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002722 AUDIO_DEVICE_IN_VOICE_CALL) ||
2723 (is_single_device_type_equal(&usecase->device_list,
2724 AUDIO_DEVICE_IN_USB_HEADSET) &&
2725 is_single_device_type_equal(&vc_usecase->device_list,
2726 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 in_snd_device = vc_usecase->in_snd_device;
2728 out_snd_device = vc_usecase->out_snd_device;
2729 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002730 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002731 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002732 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002733 if ((voip_usecase != NULL) &&
2734 (usecase->type == PCM_PLAYBACK) &&
2735 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002736 out_snd_device_backend_match = platform_check_backends_match(
2737 voip_usecase->out_snd_device,
2738 platform_get_output_snd_device(
2739 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302740 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002741 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002742 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2743 (is_codec_backend_out_device_type(&usecase->device_list) ||
2744 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002745 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002746 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002747 in_snd_device = voip_usecase->in_snd_device;
2748 out_snd_device = voip_usecase->out_snd_device;
2749 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002750 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002751 hfp_ucid = audio_extn_hfp_get_usecase();
2752 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002753 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002754 in_snd_device = hfp_usecase->in_snd_device;
2755 out_snd_device = hfp_usecase->out_snd_device;
2756 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002757 }
2758 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302759 if (usecase->stream.out == NULL) {
2760 ALOGE("%s: stream.out is NULL", __func__);
2761 return -EINVAL;
2762 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002763 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002765 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002766 struct stream_out *voip_out = adev->primary_output;
2767 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002768 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002769 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2770 else
2771 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 usecase->stream.out,
2773 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002774 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002775
Eric Laurent637e2d42018-11-15 12:24:31 -08002776 if (voip_usecase)
2777 voip_out = voip_usecase->stream.out;
2778
2779 if (usecase->stream.out == voip_out && voip_in != NULL)
2780 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002782 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302783 if (usecase->stream.in == NULL) {
2784 ALOGE("%s: stream.in is NULL", __func__);
2785 return -EINVAL;
2786 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002787 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002788 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002789 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002791 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002792 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002793
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002794 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002795 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002796 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2797 USECASE_AUDIO_PLAYBACK_VOIP);
2798
Carter Hsu2e429db2019-05-14 18:50:52 +08002799 usecase->stream.in->enable_ec_port = false;
2800
Zhou Song62ea0282020-03-22 19:53:01 +08002801 bool is_ha_usecase = adev->ha_proxy_enable ?
2802 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2803 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2804 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002805 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002806 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002807 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002808 } else if (adev->primary_output &&
2809 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002810 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002811 } else {
2812 /* forcing speaker o/p device to get matching i/p pair
2813 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002816 priority_in = voip_in;
2817 } else {
2818 /* get the input with the highest priority source*/
2819 priority_in = get_priority_input(adev);
2820
2821 if (!priority_in)
2822 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002823 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002824
Eric Laurent637e2d42018-11-15 12:24:31 -08002825 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002826 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302827 &out_devices,
2828 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002830 }
2831 }
2832
2833 if (out_snd_device == usecase->out_snd_device &&
2834 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302835
2836 if (!force_device_switch(usecase))
2837 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
2839
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002840 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002841 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002842 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002843 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2844 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302845 }
2846
Aalique Grahame22e49102018-12-18 14:23:57 -08002847 if (out_snd_device != SND_DEVICE_NONE &&
2848 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2849 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2850 __func__,
2851 use_case_table[uc_id],
2852 adev->last_logged_snd_device[uc_id][0],
2853 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2854 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2855 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2856 -1,
2857 out_snd_device,
2858 platform_get_snd_device_name(out_snd_device),
2859 platform_get_snd_device_acdb_id(out_snd_device));
2860 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2861 }
2862 if (in_snd_device != SND_DEVICE_NONE &&
2863 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2864 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2865 __func__,
2866 use_case_table[uc_id],
2867 adev->last_logged_snd_device[uc_id][1],
2868 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2869 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2870 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2871 -1,
2872 in_snd_device,
2873 platform_get_snd_device_name(in_snd_device),
2874 platform_get_snd_device_acdb_id(in_snd_device));
2875 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2876 }
2877
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 /*
2880 * Limitation: While in call, to do a device switch we need to disable
2881 * and enable both RX and TX devices though one of them is same as current
2882 * device.
2883 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002884 if ((usecase->type == VOICE_CALL) &&
2885 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2886 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002887 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002888 }
2889
2890 if (((usecase->type == VOICE_CALL) ||
2891 (usecase->type == VOIP_CALL)) &&
2892 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2893 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302894 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002895 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002896 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002897
2898 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302899 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002900 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002901 }
2902
Aalique Grahame22e49102018-12-18 14:23:57 -08002903 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2904 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002905 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302906 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002907 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2908 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2909 else
2910 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302911 }
2912
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002913 /* Disable current sound devices */
2914 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002915 disable_audio_route(adev, usecase);
2916 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 }
2918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002919 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002920 disable_audio_route(adev, usecase);
2921 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 }
2923
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002924 /* Applicable only on the targets that has external modem.
2925 * New device information should be sent to modem before enabling
2926 * the devices to reduce in-call device switch time.
2927 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002928 if ((usecase->type == VOICE_CALL) &&
2929 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2930 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002931 status = platform_switch_voice_call_enable_device_config(adev->platform,
2932 out_snd_device,
2933 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002934 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002935
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002936 /* Enable new sound devices */
2937 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002938 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302939 if (platform_check_codec_asrc_support(adev->platform))
2940 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002941 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002944 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302945 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002946 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002948
Lakshman Chaluvaraju4c29a492020-10-28 19:29:23 +05302949 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -07002950 status = platform_switch_voice_call_device_post(adev->platform,
2951 out_snd_device,
2952 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002953
sangwoo170731f2013-06-08 15:36:36 +09002954 usecase->in_snd_device = in_snd_device;
2955 usecase->out_snd_device = out_snd_device;
2956
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302957 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2958 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302959 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002960 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002961 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002962 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2963 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2964 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2965 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2966 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2967 /*
2968 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2969 * configured device sample rate, if not update the COPP rate to be equal to the
2970 * device sample rate, else open COPP at stream sample rate
2971 */
2972 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2973 usecase->stream.out->sample_rate,
2974 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302975 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302976 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2977 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302978 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002979 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2980 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2981 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2982 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002983 }
2984 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002985
Shalini Manjunatha8ae54892020-12-29 13:02:25 +05302986 if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) {
2987 struct stream_in *voip_in = get_voice_communication_input(adev);
2988 struct audio_usecase *voip_in_usecase = NULL;
2989 voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP);
2990 if (voip_in != NULL &&
2991 voip_in_usecase != NULL &&
2992 !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER ||
2993 out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) &&
2994 (voip_in_usecase->in_snd_device ==
2995 platform_get_input_snd_device(adev->platform, voip_in,
2996 &usecase->stream.out->device_list,usecase->type))) {
2997 /*
2998 * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path
2999 * for enabling echo-reference-voip with correct port
3000 */
3001 ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__);
3002 disable_audio_route(adev, voip_in_usecase);
3003 disable_snd_device(adev, voip_in_usecase->in_snd_device);
3004 enable_snd_device(adev, voip_in_usecase->in_snd_device);
3005 enable_audio_route(adev, voip_in_usecase);
3006 }
3007 }
3008
3009
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003010 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08003011
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003012 /* If input stream is already running then effect needs to be
3013 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003014 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003015 check_and_enable_effect(adev);
3016
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003017 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003018 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303019 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003020 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3021
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003022 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303023 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003024 voice_extn_compress_voip_is_started(adev))
3025 voice_set_sidetone(adev, out_snd_device, true);
3026 }
3027
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003028 /* Applicable only on the targets that has external modem.
3029 * Enable device command should be sent to modem only after
3030 * enabling voice call mixer controls
3031 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003032 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003033 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3034 out_snd_device,
3035 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303036
3037 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003038 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303039 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003040 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303041 if (is_bt_soc_on(adev) == false){
3042 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003043 if (in->pcm != NULL)
3044 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303045 }
3046 }
3047 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3048 && usecase->stream.out->started) {
3049 if (is_bt_soc_on(adev) == false) {
3050 ALOGD("BT SCO/A2DP disconnected while in connection");
3051 out_standby_l(&usecase->stream.out->stream.common);
3052 }
3053 }
3054 } else if ((usecase->stream.out != NULL) &&
3055 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303056 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3057 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003058 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303059 usecase->stream.out->started) {
3060 if (is_bt_soc_on(adev) == false) {
3061 ALOGD("BT SCO/A2dp disconnected while in connection");
3062 out_standby_l(&usecase->stream.out->stream.common);
3063 }
3064 }
3065 }
3066
Yung Ti Su70cb8242018-06-22 17:38:47 +08003067 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003068 struct stream_out *voip_out = voip_usecase->stream.out;
3069 audio_extn_utils_send_app_type_gain(adev,
3070 voip_out->app_type_cfg.app_type,
3071 &voip_out->app_type_cfg.gain[0]);
3072 }
3073
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303074 ALOGD("%s: done",__func__);
3075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 return status;
3077}
3078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079static int stop_input_stream(struct stream_in *in)
3080{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303081 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303083
3084 if (in == NULL) {
3085 ALOGE("%s: stream_in ptr is NULL", __func__);
3086 return -EINVAL;
3087 }
3088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003090 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091
Eric Laurent994a6932013-07-17 11:51:42 -07003092 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003093 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 uc_info = get_usecase_from_list(adev, in->usecase);
3095 if (uc_info == NULL) {
3096 ALOGE("%s: Could not find the usecase (%d) in the list",
3097 __func__, in->usecase);
3098 return -EINVAL;
3099 }
3100
Carter Hsu2e429db2019-05-14 18:50:52 +08003101 priority_in = get_priority_input(adev);
3102
Derek Chenea197282019-01-07 17:35:01 -08003103 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3104 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003105
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003106 /* Close in-call recording streams */
3107 voice_check_and_stop_incall_rec_usecase(adev, in);
3108
Eric Laurent150dbfe2013-02-27 14:31:02 -08003109 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003110 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003111
3112 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003113 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003115 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303116 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3117
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003118 list_remove(&uc_info->list);
3119 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120
Carter Hsu2e429db2019-05-14 18:50:52 +08003121 if (priority_in == in) {
3122 priority_in = get_priority_input(adev);
3123 if (priority_in)
3124 select_devices(adev, priority_in->usecase);
3125 }
3126
Vatsal Buchac09ae062018-11-14 13:25:08 +05303127 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003128 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 return ret;
3130}
3131
3132int start_input_stream(struct stream_in *in)
3133{
3134 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003135 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303137
3138 if (in == NULL) {
3139 ALOGE("%s: stream_in ptr is NULL", __func__);
3140 return -EINVAL;
3141 }
3142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003144 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003145 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Mingming Yin2664a5b2015-09-03 10:53:11 -07003147 if (get_usecase_from_list(adev, usecase) == NULL)
3148 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303149 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3150 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003151
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303152 if (CARD_STATUS_OFFLINE == in->card_status||
3153 CARD_STATUS_OFFLINE == adev->card_status) {
3154 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303155 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303156 goto error_config;
3157 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003159 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303160 if (!adev->bt_sco_on) {
3161 ALOGE("%s: SCO profile is not ready, return error", __func__);
3162 ret = -EIO;
3163 goto error_config;
3164 }
3165 }
3166
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003167 /* Check if source matches incall recording usecase criteria */
3168 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3169 if (ret)
3170 goto error_config;
3171 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003172 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3173
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303174 if (audio_extn_cin_attached_usecase(in))
3175 audio_extn_cin_acquire_usecase(in);
3176
Mingming Yin2664a5b2015-09-03 10:53:11 -07003177 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3178 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3179 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Weiyin Jiang04949102020-09-10 16:10:51 +08003180 ret = -EINVAL;
3181 goto error_config;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003182 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003183
Eric Laurentb23d5282013-05-14 15:27:20 -07003184 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (in->pcm_device_id < 0) {
3186 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3187 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003188 ret = -EINVAL;
3189 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003193
3194 if (!uc_info) {
3195 ret = -ENOMEM;
3196 goto error_config;
3197 }
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 uc_info->id = in->usecase;
3200 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003201 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003202 list_init(&uc_info->device_list);
3203 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003204 uc_info->in_snd_device = SND_DEVICE_NONE;
3205 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003207 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003208 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303209 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3210 adev->perf_lock_opts,
3211 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003212 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213
Derek Chenea197282019-01-07 17:35:01 -08003214 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3215 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003216
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303217 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3218
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303219 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303220 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303221 if (ret)
3222 goto error_open;
3223 else
3224 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 }
3226
Haynes Mathew George16081042017-05-31 17:16:49 -07003227 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 ALOGE("%s: pcm stream not ready", __func__);
3230 goto error_open;
3231 }
3232 ret = pcm_start(in->pcm);
3233 if (ret < 0) {
3234 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3235 goto error_open;
3236 }
3237 } else {
3238 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3239 unsigned int pcm_open_retry_count = 0;
3240
Zhou Song62ea0282020-03-22 19:53:01 +08003241 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3242 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003243 flags |= PCM_MMAP | PCM_NOIRQ;
3244 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3245 } else if (in->realtime) {
3246 flags |= PCM_MMAP | PCM_NOIRQ;
3247 }
3248
Garmond Leunge2433c32017-09-28 21:51:22 -07003249 if (audio_extn_ffv_get_stream() == in) {
3250 ALOGD("%s: ffv stream, update pcm config", __func__);
3251 audio_extn_ffv_update_pcm_config(&config);
3252 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3254 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3255
3256 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003257 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003258 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003259 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303261 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303262 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3263 adev->card_status = CARD_STATUS_OFFLINE;
3264 in->card_status = CARD_STATUS_OFFLINE;
3265 ret = -EIO;
3266 goto error_open;
3267 }
3268
Haynes Mathew George16081042017-05-31 17:16:49 -07003269 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3270 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3271 if (in->pcm != NULL) {
3272 pcm_close(in->pcm);
3273 in->pcm = NULL;
3274 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003275 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 ret = -EIO;
3277 goto error_open;
3278 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003279 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003280 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3281 continue;
3282 }
3283 break;
3284 }
3285
3286 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003287 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003288 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003289 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003290 if (ret < 0) {
3291 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3292 pcm_close(in->pcm);
3293 in->pcm = NULL;
3294 goto error_open;
3295 }
3296 register_in_stream(in);
3297 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003298 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003299 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003300 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003301 if (ret < 0) {
3302 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003303 pcm_close(in->pcm);
3304 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003305 goto error_open;
3306 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003307 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003308 }
3309
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003310 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003311 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3312 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003313
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003314 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303315 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3316
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303317done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003318 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303319 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003320 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303321 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003322 return ret;
3323
3324error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003325 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303326 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003328
Eric Laurentc8400632013-02-14 19:04:54 -08003329error_config:
Weiyin Jiang04949102020-09-10 16:10:51 +08003330 if (audio_extn_cin_attached_usecase(in))
3331 audio_extn_cin_close_input_stream(in);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303332 /*
3333 * sleep 50ms to allow sufficient time for kernel
3334 * drivers to recover incases like SSR.
3335 */
3336 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003337 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303338 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340}
3341
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003342void lock_input_stream(struct stream_in *in)
3343{
3344 pthread_mutex_lock(&in->pre_lock);
3345 pthread_mutex_lock(&in->lock);
3346 pthread_mutex_unlock(&in->pre_lock);
3347}
3348
3349void lock_output_stream(struct stream_out *out)
3350{
3351 pthread_mutex_lock(&out->pre_lock);
3352 pthread_mutex_lock(&out->lock);
3353 pthread_mutex_unlock(&out->pre_lock);
3354}
3355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356/* must be called with out->lock locked */
3357static int send_offload_cmd_l(struct stream_out* out, int command)
3358{
3359 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3360
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003361 if (!cmd) {
3362 ALOGE("failed to allocate mem for command 0x%x", command);
3363 return -ENOMEM;
3364 }
3365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 ALOGVV("%s %d", __func__, command);
3367
3368 cmd->cmd = command;
3369 list_add_tail(&out->offload_cmd_list, &cmd->node);
3370 pthread_cond_signal(&out->offload_cond);
3371 return 0;
3372}
3373
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003374/* must be called with out->lock and latch lock */
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375static void stop_compressed_output_l(struct stream_out *out)
3376{
3377 out->offload_state = OFFLOAD_STATE_IDLE;
3378 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003379 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 if (out->compr != NULL) {
3381 compress_stop(out->compr);
3382 while (out->offload_thread_blocked) {
3383 pthread_cond_wait(&out->cond, &out->lock);
3384 }
3385 }
3386}
3387
Varun Balaraje49253e2017-07-06 19:48:56 +05303388bool is_interactive_usecase(audio_usecase_t uc_id)
3389{
3390 unsigned int i;
3391 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3392 if (uc_id == interactive_usecases[i])
3393 return true;
3394 }
3395 return false;
3396}
3397
3398static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3399{
3400 audio_usecase_t ret_uc = USECASE_INVALID;
3401 unsigned int intract_uc_index;
3402 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3403
3404 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3405 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3406 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3407 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3408 ret_uc = interactive_usecases[intract_uc_index];
3409 break;
3410 }
3411 }
3412
3413 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3414 return ret_uc;
3415}
3416
3417static void free_interactive_usecase(struct audio_device *adev,
3418 audio_usecase_t uc_id)
3419{
3420 unsigned int interact_uc_index;
3421 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3422
3423 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3424 if (interactive_usecases[interact_uc_index] == uc_id) {
3425 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3426 break;
3427 }
3428 }
3429 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3430}
3431
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003432bool is_offload_usecase(audio_usecase_t uc_id)
3433{
3434 unsigned int i;
3435 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3436 if (uc_id == offload_usecases[i])
3437 return true;
3438 }
3439 return false;
3440}
3441
Dhananjay Kumarac341582017-02-23 23:42:25 +05303442static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003443{
vivek mehta446c3962015-09-14 10:57:35 -07003444 audio_usecase_t ret_uc = USECASE_INVALID;
3445 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003446 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003447 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303448 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003449 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3450 else
3451 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003452
vivek mehta446c3962015-09-14 10:57:35 -07003453 pthread_mutex_lock(&adev->lock);
3454 if (get_usecase_from_list(adev, ret_uc) != NULL)
3455 ret_uc = USECASE_INVALID;
3456 pthread_mutex_unlock(&adev->lock);
3457
3458 return ret_uc;
3459 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003460
3461 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003462 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3463 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3464 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3465 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003466 break;
3467 }
3468 }
vivek mehta446c3962015-09-14 10:57:35 -07003469
3470 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3471 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003472}
3473
3474static void free_offload_usecase(struct audio_device *adev,
3475 audio_usecase_t uc_id)
3476{
vivek mehta446c3962015-09-14 10:57:35 -07003477 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003478 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003479
3480 if (!adev->multi_offload_enable)
3481 return;
3482
3483 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3484 if (offload_usecases[offload_uc_index] == uc_id) {
3485 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003486 break;
3487 }
3488 }
3489 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3490}
3491
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492static void *offload_thread_loop(void *context)
3493{
3494 struct stream_out *out = (struct stream_out *) context;
3495 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003496 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003499 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3501
3502 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003503 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003504 out->offload_state = OFFLOAD_STATE_IDLE;
3505 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 for (;;) {
3507 struct offload_cmd *cmd = NULL;
3508 stream_callback_event_t event;
3509 bool send_callback = false;
3510
3511 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3512 __func__, list_empty(&out->offload_cmd_list),
3513 out->offload_state);
3514 if (list_empty(&out->offload_cmd_list)) {
3515 ALOGV("%s SLEEPING", __func__);
3516 pthread_cond_wait(&out->offload_cond, &out->lock);
3517 ALOGV("%s RUNNING", __func__);
3518 continue;
3519 }
3520
3521 item = list_head(&out->offload_cmd_list);
3522 cmd = node_to_item(item, struct offload_cmd, node);
3523 list_remove(item);
3524
3525 ALOGVV("%s STATE %d CMD %d out->compr %p",
3526 __func__, out->offload_state, cmd->cmd, out->compr);
3527
3528 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3529 free(cmd);
3530 break;
3531 }
3532
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003533 // allow OFFLOAD_CMD_ERROR reporting during standby
3534 // this is needed to handle failures during compress_open
3535 // Note however that on a pause timeout, the stream is closed
3536 // and no offload usecase will be active. Therefore this
3537 // special case is needed for compress_open failures alone
3538 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3539 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003541 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542 pthread_cond_signal(&out->cond);
3543 continue;
3544 }
3545 out->offload_thread_blocked = true;
3546 pthread_mutex_unlock(&out->lock);
3547 send_callback = false;
3548 switch(cmd->cmd) {
3549 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003550 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003552 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 send_callback = true;
3554 event = STREAM_CBK_EVENT_WRITE_READY;
3555 break;
3556 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003557 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303558 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003559 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303560 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003561 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303562 if (ret < 0)
3563 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303564 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303565 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003566 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003567 else
3568 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003569 if (-ENETRESET != ret && !(-EINTR == ret &&
3570 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303571 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303572 pthread_mutex_lock(&out->lock);
3573 out->send_new_metadata = 1;
3574 out->send_next_track_params = true;
3575 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303576 event = STREAM_CBK_EVENT_DRAIN_READY;
3577 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3578 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303579 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 break;
3581 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003582 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003583 ret = compress_drain(out->compr);
3584 ALOGD("copl(%p):out of compress_drain", out);
3585 // EINTR check avoids drain interruption due to SSR
3586 if (-ENETRESET != ret && !(-EINTR == ret &&
3587 CARD_STATUS_OFFLINE == out->card_status)) {
3588 send_callback = true;
3589 event = STREAM_CBK_EVENT_DRAIN_READY;
3590 } else
3591 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003592 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303593 case OFFLOAD_CMD_ERROR:
3594 ALOGD("copl(%p): sending error callback to AF", out);
3595 send_callback = true;
3596 event = STREAM_CBK_EVENT_ERROR;
3597 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003598 default:
3599 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3600 break;
3601 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003602 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003603 out->offload_thread_blocked = false;
3604 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003605 if (send_callback && out->client_callback) {
3606 ALOGVV("%s: sending client_callback event %d", __func__, event);
3607 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003608 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 free(cmd);
3610 }
3611
3612 pthread_cond_signal(&out->cond);
3613 while (!list_empty(&out->offload_cmd_list)) {
3614 item = list_head(&out->offload_cmd_list);
3615 list_remove(item);
3616 free(node_to_item(item, struct offload_cmd, node));
3617 }
3618 pthread_mutex_unlock(&out->lock);
3619
3620 return NULL;
3621}
3622
3623static int create_offload_callback_thread(struct stream_out *out)
3624{
3625 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3626 list_init(&out->offload_cmd_list);
3627 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3628 offload_thread_loop, out);
3629 return 0;
3630}
3631
3632static int destroy_offload_callback_thread(struct stream_out *out)
3633{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003634 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003635 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003636 stop_compressed_output_l(out);
3637 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3638
Weiyin Jiangd5974e62020-09-08 20:28:22 +08003639 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003640 pthread_mutex_unlock(&out->lock);
3641 pthread_join(out->offload_thread, (void **) NULL);
3642 pthread_cond_destroy(&out->offload_cond);
3643
3644 return 0;
3645}
3646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647static int stop_output_stream(struct stream_out *out)
3648{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303649 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 struct audio_usecase *uc_info;
3651 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003652 bool has_voip_usecase =
3653 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654
Eric Laurent994a6932013-07-17 11:51:42 -07003655 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003656 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 uc_info = get_usecase_from_list(adev, out->usecase);
3658 if (uc_info == NULL) {
3659 ALOGE("%s: Could not find the usecase (%d) in the list",
3660 __func__, out->usecase);
3661 return -EINVAL;
3662 }
3663
Zhou Song1f93fa52020-11-20 13:57:39 +08003664 out->a2dp_muted = false;
3665
Derek Chenea197282019-01-07 17:35:01 -08003666 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3667 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003668
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003669 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303670 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003671 if (adev->visualizer_stop_output != NULL)
3672 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003673
3674 audio_extn_dts_remove_state_notifier_node(out->usecase);
3675
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003676 if (adev->offload_effects_stop_output != NULL)
3677 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003678 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3679 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3680 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003681 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003682
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003683 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3684 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003685 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003686 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003687
Eric Laurent150dbfe2013-02-27 14:31:02 -08003688 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003689 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003690
3691 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003692 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693
Aalique Grahame22e49102018-12-18 14:23:57 -08003694 audio_extn_extspk_update(adev->extspk);
3695
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003696 if (is_offload_usecase(out->usecase)) {
3697 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3698 adev->dsp_bit_width_enforce_mode,
3699 false);
3700 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003701 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003702 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3703 false);
3704
3705 if (ret != 0)
3706 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3707 /* default service interval was successfully updated,
3708 reopen USB backend with new service interval */
3709 ret = 0;
3710 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003711
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003712 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303713 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003714 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303715 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003716 ALOGV("Disable passthrough , reset mixer to pcm");
3717 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003718#ifdef AUDIO_GKI_ENABLED
3719 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3720 out->compr_config.codec->reserved[0] = 0;
3721#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003722 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003723#endif
Mingming Yin21854652016-04-13 11:54:02 -07003724 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003725 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3726 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003727
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303728 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003729 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303730 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303731
Manish Dewangan21a850a2017-08-14 12:03:55 +05303732 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003733 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3734 if (ret < 0)
3735 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3736 }
3737
juyuchen2d415992018-11-16 14:15:16 +08003738 /* 1) media + voip output routing to handset must route media back to
3739 speaker when voip stops.
3740 2) trigger voip input to reroute when voip output changes to
3741 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003742 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003743 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003744 struct listnode *node;
3745 struct audio_usecase *usecase;
3746 list_for_each(node, &adev->usecase_list) {
3747 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003748 if ((usecase->type == PCM_CAPTURE &&
3749 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3750 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003751 continue;
3752
3753 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3754 __func__, usecase->id, use_case_table[usecase->id],
3755 out->usecase, use_case_table[out->usecase]);
3756 select_devices(adev, usecase->id);
3757 }
3758 }
3759
Garmond Leung5fd0b552018-04-17 11:56:12 -07003760 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003761 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 return ret;
3763}
3764
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003765struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3766 unsigned int flags, unsigned int pcm_open_retry_count,
3767 struct pcm_config *config)
3768{
3769 struct pcm* pcm = NULL;
3770
3771 while (1) {
3772 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3773 if (pcm == NULL || !pcm_is_ready(pcm)) {
3774 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3775 if (pcm != NULL) {
3776 pcm_close(pcm);
3777 pcm = NULL;
3778 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003779 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003780 return NULL;
3781
Weiyin Jiang72197252019-10-09 11:49:32 +08003782 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003783 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3784 continue;
3785 }
3786 break;
3787 }
3788
3789 if (pcm_is_ready(pcm)) {
3790 int ret = pcm_prepare(pcm);
3791 if (ret < 0) {
3792 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3793 pcm_close(pcm);
3794 pcm = NULL;
3795 }
3796 }
3797
3798 return pcm;
3799}
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801int start_output_stream(struct stream_out *out)
3802{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 struct audio_usecase *uc_info;
3805 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003806 char mixer_ctl_name[128];
3807 struct mixer_ctl *ctl = NULL;
3808 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303809 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003810 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811
Haynes Mathew George380745d2017-10-04 15:27:45 -07003812 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003813 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3814 ret = -EINVAL;
3815 goto error_config;
3816 }
3817
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003818 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303819 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003820 get_device_types(&out->device_list), is_haptic_usecase);
3821
3822 bool is_speaker_active = compare_device_type(&out->device_list,
3823 AUDIO_DEVICE_OUT_SPEAKER);
3824 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3825 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303826
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303827 if (CARD_STATUS_OFFLINE == out->card_status ||
3828 CARD_STATUS_OFFLINE == adev->card_status) {
3829 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303830 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003831 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303832 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303833
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003834 //Update incall music usecase to reflect correct voice session
3835 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3836 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3837 if (ret != 0) {
3838 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3839 __func__, ret);
3840 goto error_config;
3841 }
3842 }
3843
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003844 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003845 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003846 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303847 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303848 } else {
Zhou Song9ebf6792020-09-23 22:49:01 +08003849 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303850 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3851 ret = -EAGAIN;
3852 goto error_config;
3853 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303854 }
3855 }
3856 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003857 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303858 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003859 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303860 //combo usecase just by pass a2dp
3861 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003862 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303863 } else {
3864 ALOGE("%s: SCO profile is not ready, return error", __func__);
3865 ret = -EAGAIN;
3866 goto error_config;
3867 }
3868 }
3869 }
3870
Eric Laurentb23d5282013-05-14 15:27:20 -07003871 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 if (out->pcm_device_id < 0) {
3873 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3874 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003875 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003876 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 }
3878
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003879 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003880 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3881 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 if (adev->haptic_pcm_device_id < 0) {
3883 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3884 __func__, adev->haptic_pcm_device_id, out->usecase);
3885 ret = -EINVAL;
3886 goto error_config;
3887 }
3888 }
3889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003891
3892 if (!uc_info) {
3893 ret = -ENOMEM;
3894 goto error_config;
3895 }
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 uc_info->id = out->usecase;
3898 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003899 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003900 list_init(&uc_info->device_list);
3901 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003902 uc_info->in_snd_device = SND_DEVICE_NONE;
3903 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003904
3905 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003906 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003907 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3908 /* USB backend is not reopened immediately.
3909 This is eventually done as part of select_devices */
3910 }
3911
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003912 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913
Wei Wangf7ca6c92017-11-21 14:51:20 -08003914 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303915 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3916 adev->perf_lock_opts,
3917 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303918
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003919 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303920 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303921 if (audio_extn_passthru_is_enabled() &&
3922 audio_extn_passthru_is_passthrough_stream(out)) {
3923 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303924 }
3925 }
3926
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003927 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003928 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303929 if (!a2dp_combo) {
3930 check_a2dp_restore_l(adev, out, false);
3931 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003932 struct listnode dev;
3933 list_init(&dev);
3934 assign_devices(&dev, &out->device_list);
3935 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3936 reassign_device_list(&out->device_list,
3937 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003938 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003939 reassign_device_list(&out->device_list,
3940 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303941 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003942 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303943 }
3944 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303945 select_devices(adev, out->usecase);
3946 if (is_a2dp_out_device_type(&out->device_list) &&
3947 !adev->a2dp_started) {
3948 if (is_speaker_active || is_speaker_safe_active) {
3949 struct listnode dev;
3950 list_init(&dev);
3951 assign_devices(&dev, &out->device_list);
3952 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3953 reassign_device_list(&out->device_list,
3954 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3955 else
3956 reassign_device_list(&out->device_list,
3957 AUDIO_DEVICE_OUT_SPEAKER, "");
3958 select_devices(adev, out->usecase);
3959 assign_devices(&out->device_list, &dev);
3960 } else {
3961 ret = -EINVAL;
3962 goto error_open;
3963 }
3964 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303965 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003966
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003967 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3968 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003969 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003970 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003971
Derek Chenea197282019-01-07 17:35:01 -08003972 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3973 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003974
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003975 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3976 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003977
3978 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003979 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003980 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3981 ALOGE("%s: pcm stream not ready", __func__);
3982 goto error_open;
3983 }
3984 ret = pcm_start(out->pcm);
3985 if (ret < 0) {
3986 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3987 goto error_open;
3988 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003989 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003990 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003991 unsigned int flags = PCM_OUT;
3992 unsigned int pcm_open_retry_count = 0;
3993 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3994 flags |= PCM_MMAP | PCM_NOIRQ;
3995 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003996 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003997 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003998 } else
3999 flags |= PCM_MONOTONIC;
4000
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004001 if ((adev->vr_audio_mode_enabled) &&
4002 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
4003 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4004 "PCM_Dev %d Topology", out->pcm_device_id);
4005 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4006 if (!ctl) {
4007 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
4008 __func__, mixer_ctl_name);
4009 } else {
4010 //if success use ULLPP
4011 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
4012 __func__, mixer_ctl_name, out->pcm_device_id);
4013 //There is a still a possibility that some sessions
4014 // that request for FAST|RAW when 3D audio is active
4015 //can go through ULLPP. Ideally we expects apps to
4016 //listen to audio focus and stop concurrent playback
4017 //Also, we will look for mode flag (voice_in_communication)
4018 //before enabling the realtime flag.
4019 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
4020 }
4021 }
4022
Surendar Karka91fa3682018-07-02 18:12:12 +05304023 if (out->realtime)
4024 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4025 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
4026
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004027 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
4028 flags, pcm_open_retry_count,
4029 &(out->config));
4030 if (out->pcm == NULL) {
4031 ret = -EIO;
4032 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004033 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004034
4035 if (is_haptic_usecase) {
4036 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4037 adev->haptic_pcm_device_id,
4038 flags, pcm_open_retry_count,
4039 &(adev->haptics_config));
4040 // failure to open haptics pcm shouldnt stop audio,
4041 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004042
4043 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4044 ALOGD("%s: enable haptic audio synchronization", __func__);
4045 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4046 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004047 }
4048
Surendar Karka91fa3682018-07-02 18:12:12 +05304049 if (!out->realtime)
4050 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304051 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004052
Zhou Song2b8f28f2017-09-11 10:51:38 +08004053 // apply volume for voip playback after path is set up
4054 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4055 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304056 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4057 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304058 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4059 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004060 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4061 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304062 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004063 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004064 /*
4065 * set custom channel map if:
4066 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4067 * 2. custom channel map has been set by client
4068 * else default channel map of FC/FR/FL can always be set to DSP
4069 */
4070 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4071 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4072 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004073 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4074 adev->dsp_bit_width_enforce_mode,
4075 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004077 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004078 out->compr = compress_open(adev->snd_card,
4079 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004080 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004081 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304082 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304083 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4084 adev->card_status = CARD_STATUS_OFFLINE;
4085 out->card_status = CARD_STATUS_OFFLINE;
4086 ret = -EIO;
4087 goto error_open;
4088 }
4089
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004090 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004091 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004092 compress_close(out->compr);
4093 out->compr = NULL;
4094 ret = -EIO;
4095 goto error_open;
4096 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304097 /* compress_open sends params of the track, so reset the flag here */
4098 out->is_compr_metadata_avail = false;
4099
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004100 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004102
Fred Oh3f43e742015-03-04 18:42:34 -08004103 /* Since small bufs uses blocking writes, a write will be blocked
4104 for the default max poll time (20s) in the event of an SSR.
4105 Reduce the poll time to observe and deal with SSR faster.
4106 */
Ashish Jain5106d362016-05-11 19:23:33 +05304107 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004108 compress_set_max_poll_wait(out->compr, 1000);
4109 }
4110
Manish Dewangan69426c82017-01-30 17:35:36 +05304111 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304112 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304113
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004114 audio_extn_dts_create_state_notifier_node(out->usecase);
4115 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4116 popcount(out->channel_mask),
4117 out->playback_started);
4118
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004119#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304120 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004121 audio_extn_dolby_send_ddp_endp_params(adev);
4122#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304123 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4124 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004125 if (adev->visualizer_start_output != NULL)
4126 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4127 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304128 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004129 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004130 }
Derek Chenf13dd492018-11-13 14:53:51 -08004131
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004132 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004133 /* Update cached volume from media to offload/direct stream */
4134 struct listnode *node = NULL;
4135 list_for_each(node, &adev->active_outputs_list) {
4136 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4137 streams_output_ctxt_t,
4138 list);
4139 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4140 out->volume_l = out_ctxt->output->volume_l;
4141 out->volume_r = out_ctxt->output->volume_r;
4142 }
4143 }
4144 out_set_compr_volume(&out->stream,
4145 out->volume_l, out->volume_r);
4146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004148
4149 if (ret == 0) {
4150 register_out_stream(out);
4151 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004152 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4153 ALOGE("%s: pcm stream not ready", __func__);
4154 goto error_open;
4155 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004156 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004157 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004158 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004159 if (ret < 0)
4160 goto error_open;
4161 }
4162 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004163 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304164 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004165 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004166
vivek mehtad15d2bf2019-05-17 13:35:10 -07004167 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4168 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4169 audio_low_latency_hint_start();
4170 }
4171
Manish Dewangan21a850a2017-08-14 12:03:55 +05304172 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004173 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004174 if (ret < 0)
4175 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4176 }
4177
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004178 // consider a scenario where on pause lower layers are tear down.
4179 // so on resume, swap mixer control need to be sent only when
4180 // backend is active, hence rather than sending from enable device
4181 // sending it from start of streamtream
4182
4183 platform_set_swap_channels(adev, true);
4184
Haynes Mathew George380745d2017-10-04 15:27:45 -07004185 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304186 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004187 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004188error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004189 if (adev->haptic_pcm) {
4190 pcm_close(adev->haptic_pcm);
4191 adev->haptic_pcm = NULL;
4192 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004193 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304194 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004196error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304197 /*
4198 * sleep 50ms to allow sufficient time for kernel
4199 * drivers to recover incases like SSR.
4200 */
4201 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004202error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004203 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304204 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206}
4207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208static int check_input_parameters(uint32_t sample_rate,
4209 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004210 int channel_count,
4211 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004213 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304215 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4216 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4217 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004218 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004219 !audio_extn_compr_cap_format_supported(format) &&
4220 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004221 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004222
Aalique Grahame22e49102018-12-18 14:23:57 -08004223 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4224 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4225 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4226 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4227 return -EINVAL;
4228 }
4229
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004230 switch (channel_count) {
4231 case 1:
4232 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304233 case 3:
4234 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004235 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004236 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304237 case 10:
4238 case 12:
4239 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004240 break;
4241 default:
4242 ret = -EINVAL;
4243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244
4245 switch (sample_rate) {
4246 case 8000:
4247 case 11025:
4248 case 12000:
4249 case 16000:
4250 case 22050:
4251 case 24000:
4252 case 32000:
4253 case 44100:
4254 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004255 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304256 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004257 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304258 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 break;
4260 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004261 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 }
4263
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265}
4266
Naresh Tanniru04f71882018-06-26 17:46:22 +05304267
4268/** Add a value in a list if not already present.
4269 * @return true if value was successfully inserted or already present,
4270 * false if the list is full and does not contain the value.
4271 */
4272static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4273 for (size_t i = 0; i < list_length; i++) {
4274 if (list[i] == value) return true; // value is already present
4275 if (list[i] == 0) { // no values in this slot
4276 list[i] = value;
4277 return true; // value inserted
4278 }
4279 }
4280 return false; // could not insert value
4281}
4282
4283/** Add channel_mask in supported_channel_masks if not already present.
4284 * @return true if channel_mask was successfully inserted or already present,
4285 * false if supported_channel_masks is full and does not contain channel_mask.
4286 */
4287static void register_channel_mask(audio_channel_mask_t channel_mask,
4288 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4289 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4290 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4291}
4292
4293/** Add format in supported_formats if not already present.
4294 * @return true if format was successfully inserted or already present,
4295 * false if supported_formats is full and does not contain format.
4296 */
4297static void register_format(audio_format_t format,
4298 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4299 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4300 "%s: stream can not declare supporting its format %x", __func__, format);
4301}
4302/** Add sample_rate in supported_sample_rates if not already present.
4303 * @return true if sample_rate was successfully inserted or already present,
4304 * false if supported_sample_rates is full and does not contain sample_rate.
4305 */
4306static void register_sample_rate(uint32_t sample_rate,
4307 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4308 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4309 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4310}
4311
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004312static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4313{
4314 uint32_t high = num1, low = num2, temp = 0;
4315
4316 if (!num1 || !num2)
4317 return 0;
4318
4319 if (num1 < num2) {
4320 high = num2;
4321 low = num1;
4322 }
4323
4324 while (low != 0) {
4325 temp = low;
4326 low = high % low;
4327 high = temp;
4328 }
4329 return (num1 * num2)/high;
4330}
4331
4332static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4333{
4334 uint32_t remainder = 0;
4335
4336 if (!multiplier)
4337 return num;
4338
4339 remainder = num % multiplier;
4340 if (remainder)
4341 num += (multiplier - remainder);
4342
4343 return num;
4344}
4345
Aalique Grahame22e49102018-12-18 14:23:57 -08004346static size_t get_stream_buffer_size(size_t duration_ms,
4347 uint32_t sample_rate,
4348 audio_format_t format,
4349 int channel_count,
4350 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351{
4352 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004353 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354
Aalique Grahame22e49102018-12-18 14:23:57 -08004355 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004356 if (is_low_latency)
4357 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304358
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004359 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004360 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361
Ralf Herzbd08d632018-09-28 15:50:49 +02004362 /* make sure the size is multiple of 32 bytes and additionally multiple of
4363 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004364 * At 48 kHz mono 16-bit PCM:
4365 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4366 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004367 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004368 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004369 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004370
4371 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372}
4373
Aalique Grahame22e49102018-12-18 14:23:57 -08004374static size_t get_input_buffer_size(uint32_t sample_rate,
4375 audio_format_t format,
4376 int channel_count,
4377 bool is_low_latency)
4378{
4379 /* Don't know if USB HIFI in this context so use true to be conservative */
4380 if (check_input_parameters(sample_rate, format, channel_count,
4381 true /*is_usb_hifi */) != 0)
4382 return 0;
4383
4384 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4385 sample_rate,
4386 format,
4387 channel_count,
4388 is_low_latency);
4389}
4390
Derek Chenf6318be2017-06-12 17:16:24 -04004391size_t get_output_period_size(uint32_t sample_rate,
4392 audio_format_t format,
4393 int channel_count,
4394 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304395{
4396 size_t size = 0;
4397 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4398
4399 if ((duration == 0) || (sample_rate == 0) ||
4400 (bytes_per_sample == 0) || (channel_count == 0)) {
4401 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4402 bytes_per_sample, channel_count);
4403 return -EINVAL;
4404 }
4405
4406 size = (sample_rate *
4407 duration *
4408 bytes_per_sample *
4409 channel_count) / 1000;
4410 /*
4411 * To have same PCM samples for all channels, the buffer size requires to
4412 * be multiple of (number of channels * bytes per sample)
4413 * For writes to succeed, the buffer must be written at address which is multiple of 32
4414 */
4415 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4416
4417 return (size/(channel_count * bytes_per_sample));
4418}
4419
Zhou Song48453a02018-01-10 17:50:59 +08004420static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304421{
4422 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004423 uint64_t written_frames = 0;
4424 uint64_t kernel_frames = 0;
4425 uint64_t dsp_frames = 0;
4426 uint64_t signed_frames = 0;
4427 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304428
4429 /* This adjustment accounts for buffering after app processor.
4430 * It is based on estimated DSP latency per use case, rather than exact.
4431 */
George Gao9ba8a142020-07-23 14:30:03 -07004432 dsp_frames = platform_render_latency(out) *
Weiyin Jiang4813da12020-05-28 00:37:28 +08004433 out->sample_rate / 1000000LL;
Ashish Jain5106d362016-05-11 19:23:33 +05304434
Zhou Song48453a02018-01-10 17:50:59 +08004435 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004436 written_frames = out->written /
4437 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4438
Ashish Jain5106d362016-05-11 19:23:33 +05304439 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4440 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4441 * hence only estimate.
4442 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004443 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4444 kernel_frames = kernel_buffer_size /
4445 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304446
Weiyin Jiang4813da12020-05-28 00:37:28 +08004447 if (written_frames >= (kernel_frames + dsp_frames))
4448 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304449
Zhou Song48453a02018-01-10 17:50:59 +08004450 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304451 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004452 if (timestamp != NULL )
4453 *timestamp = out->writeAt;
4454 } else if (timestamp != NULL) {
4455 clock_gettime(CLOCK_MONOTONIC, timestamp);
4456 }
4457 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304458
Weiyin Jiang4813da12020-05-28 00:37:28 +08004459 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4460 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304461
4462 return actual_frames_rendered;
4463}
4464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4466{
4467 struct stream_out *out = (struct stream_out *)stream;
4468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004469 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470}
4471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004472static int out_set_sample_rate(struct audio_stream *stream __unused,
4473 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474{
4475 return -ENOSYS;
4476}
4477
4478static size_t out_get_buffer_size(const struct audio_stream *stream)
4479{
4480 struct stream_out *out = (struct stream_out *)stream;
4481
Varun Balaraje49253e2017-07-06 19:48:56 +05304482 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304483 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304484 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304485 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4486 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4487 else
4488 return out->compr_config.fragment_size;
4489 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004490 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304491 else if (is_offload_usecase(out->usecase) &&
4492 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304493 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004494
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004495 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004496 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497}
4498
4499static uint32_t out_get_channels(const struct audio_stream *stream)
4500{
4501 struct stream_out *out = (struct stream_out *)stream;
4502
4503 return out->channel_mask;
4504}
4505
4506static audio_format_t out_get_format(const struct audio_stream *stream)
4507{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004508 struct stream_out *out = (struct stream_out *)stream;
4509
4510 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511}
4512
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004513static int out_set_format(struct audio_stream *stream __unused,
4514 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515{
4516 return -ENOSYS;
4517}
4518
4519static int out_standby(struct audio_stream *stream)
4520{
4521 struct stream_out *out = (struct stream_out *)stream;
4522 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004523 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304525 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4526 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004528 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004530 if (adev->adm_deregister_stream)
4531 adev->adm_deregister_stream(adev->adm_data, out->handle);
4532
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004533 if (is_offload_usecase(out->usecase)) {
4534 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004535 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004536 pthread_mutex_unlock(&out->latch_lock);
4537 }
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004538
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004539 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004541 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4542 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304543 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004544 pthread_mutex_unlock(&adev->lock);
4545 pthread_mutex_unlock(&out->lock);
4546 ALOGD("VOIP output entered standby");
4547 return 0;
4548 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004549 if (out->pcm) {
4550 pcm_close(out->pcm);
4551 out->pcm = NULL;
4552 }
Meng Wanga09da002020-04-20 12:56:04 +08004553 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4554 if (adev->haptic_pcm) {
4555 pcm_close(adev->haptic_pcm);
4556 adev->haptic_pcm = NULL;
4557 }
4558
4559 if (adev->haptic_buffer != NULL) {
4560 free(adev->haptic_buffer);
4561 adev->haptic_buffer = NULL;
4562 adev->haptic_buffer_size = 0;
4563 }
4564 adev->haptic_pcm_device_id = 0;
4565 }
4566
Haynes Mathew George16081042017-05-31 17:16:49 -07004567 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4568 do_stop = out->playback_started;
4569 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004570
4571 if (out->mmap_shared_memory_fd >= 0) {
4572 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4573 __func__, out->mmap_shared_memory_fd);
4574 close(out->mmap_shared_memory_fd);
4575 out->mmap_shared_memory_fd = -1;
4576 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004577 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004578 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004579 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304580 out->send_next_track_params = false;
4581 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004582 out->gapless_mdata.encoder_delay = 0;
4583 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004584 if (out->compr != NULL) {
4585 compress_close(out->compr);
4586 out->compr = NULL;
4587 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004588 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004589 if (do_stop) {
4590 stop_output_stream(out);
4591 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304592 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004593 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004594 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595 }
4596 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304597 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 return 0;
4599}
4600
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304601static int out_on_error(struct audio_stream *stream)
4602{
4603 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004604 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304605
4606 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004607 // always send CMD_ERROR for offload streams, this
4608 // is needed e.g. when SSR happens within compress_open
4609 // since the stream is active, offload_callback_thread is also active.
4610 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004611 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004612 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004613 pthread_mutex_unlock(&out->latch_lock);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004614 }
4615 pthread_mutex_unlock(&out->lock);
4616
4617 status = out_standby(&out->stream.common);
4618
4619 lock_output_stream(out);
4620 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004621 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304622 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304623
4624 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4625 ALOGD("Setting previous card status if offline");
4626 out->prev_card_status_offline = true;
4627 }
4628
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304629 pthread_mutex_unlock(&out->lock);
4630
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004631 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304632}
4633
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304634/*
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004635 * standby implementation without locks, assumes that the callee already
4636 * has taken adev and out lock.
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304637 */
4638int out_standby_l(struct audio_stream *stream)
4639{
4640 struct stream_out *out = (struct stream_out *)stream;
4641 struct audio_device *adev = out->dev;
4642
4643 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4644 stream, out->usecase, use_case_table[out->usecase]);
4645
4646 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004647 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304648 if (adev->adm_deregister_stream)
4649 adev->adm_deregister_stream(adev->adm_data, out->handle);
4650
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004651 if (is_offload_usecase(out->usecase)) {
4652 pthread_mutex_lock(&out->latch_lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304653 stop_compressed_output_l(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08004654 pthread_mutex_unlock(&out->latch_lock);
4655 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304656
4657 out->standby = true;
4658 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4659 voice_extn_compress_voip_close_output_stream(stream);
4660 out->started = 0;
4661 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004662 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304663 return 0;
4664 } else if (!is_offload_usecase(out->usecase)) {
4665 if (out->pcm) {
4666 pcm_close(out->pcm);
4667 out->pcm = NULL;
4668 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004669 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4670 if (adev->haptic_pcm) {
4671 pcm_close(adev->haptic_pcm);
4672 adev->haptic_pcm = NULL;
4673 }
4674
4675 if (adev->haptic_buffer != NULL) {
4676 free(adev->haptic_buffer);
4677 adev->haptic_buffer = NULL;
4678 adev->haptic_buffer_size = 0;
4679 }
4680 adev->haptic_pcm_device_id = 0;
4681 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304682 } else {
4683 ALOGD("copl(%p):standby", out);
4684 out->send_next_track_params = false;
4685 out->is_compr_metadata_avail = false;
4686 out->gapless_mdata.encoder_delay = 0;
4687 out->gapless_mdata.encoder_padding = 0;
4688 if (out->compr != NULL) {
4689 compress_close(out->compr);
4690 out->compr = NULL;
4691 }
4692 }
4693 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004694 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304695 }
4696 ALOGD("%s: exit", __func__);
4697 return 0;
4698}
4699
Aalique Grahame22e49102018-12-18 14:23:57 -08004700static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701{
Aalique Grahame22e49102018-12-18 14:23:57 -08004702 struct stream_out *out = (struct stream_out *)stream;
4703
4704 // We try to get the lock for consistency,
4705 // but it isn't necessary for these variables.
4706 // If we're not in standby, we may be blocked on a write.
4707 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4708 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4709 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4710
Andy Hunga1f48fa2019-07-01 18:14:53 -07004711 char buffer[256]; // for statistics formatting
4712 if (!is_offload_usecase(out->usecase)) {
4713 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4714 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4715 }
4716
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004717 if (out->start_latency_ms.n > 0) {
4718 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4719 dprintf(fd, " Start latency ms: %s\n", buffer);
4720 }
4721
Aalique Grahame22e49102018-12-18 14:23:57 -08004722 if (locked) {
4723 pthread_mutex_unlock(&out->lock);
4724 }
4725
4726 // dump error info
4727 (void)error_log_dump(
4728 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730 return 0;
4731}
4732
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004733static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4734{
4735 int ret = 0;
4736 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004737
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004738 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004739 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004740 return -EINVAL;
4741 }
4742
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304743 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004744
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004745 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4746 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304747 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004748 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004749 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4750 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304751 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004752 }
4753
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004754 ALOGV("%s new encoder delay %u and padding %u", __func__,
4755 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4756
4757 return 0;
4758}
4759
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004760static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4761{
4762 return out == adev->primary_output || out == adev->voice_tx_output;
4763}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004764
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304765// note: this call is safe only if the stream_cb is
4766// removed first in close_output_stream (as is done now).
4767static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4768{
4769 if (!stream || !parms)
4770 return;
4771
4772 struct stream_out *out = (struct stream_out *)stream;
4773 struct audio_device *adev = out->dev;
4774
4775 card_status_t status;
4776 int card;
4777 if (parse_snd_card_status(parms, &card, &status) < 0)
4778 return;
4779
4780 pthread_mutex_lock(&adev->lock);
4781 bool valid_cb = (card == adev->snd_card);
4782 pthread_mutex_unlock(&adev->lock);
4783
4784 if (!valid_cb)
4785 return;
4786
4787 lock_output_stream(out);
4788 if (out->card_status != status)
4789 out->card_status = status;
4790 pthread_mutex_unlock(&out->lock);
4791
4792 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4793 use_case_table[out->usecase],
4794 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4795
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304796 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304797 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304798 if (voice_is_call_state_active(adev) &&
4799 out == adev->primary_output) {
4800 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4801 pthread_mutex_lock(&adev->lock);
4802 voice_stop_call(adev);
4803 adev->mode = AUDIO_MODE_NORMAL;
4804 pthread_mutex_unlock(&adev->lock);
4805 }
4806 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304807 return;
4808}
4809
Kevin Rocardfce19002017-08-07 19:21:36 -07004810static int get_alive_usb_card(struct str_parms* parms) {
4811 int card;
4812 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4813 !audio_extn_usb_alive(card)) {
4814 return card;
4815 }
4816 return -ENODEV;
4817}
4818
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004820 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004821{
4822 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004823 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004824 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004825 bool bypass_a2dp = false;
4826 bool reconfig = false;
4827 unsigned long service_interval = 0;
4828
4829 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004830 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4831
4832 list_init(&new_devices);
4833 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004834
4835 lock_output_stream(out);
4836 pthread_mutex_lock(&adev->lock);
4837
4838 /*
4839 * When HDMI cable is unplugged the music playback is paused and
4840 * the policy manager sends routing=0. But the audioflinger continues
4841 * to write data until standby time (3sec). As the HDMI core is
4842 * turned off, the write gets blocked.
4843 * Avoid this by routing audio to speaker until standby.
4844 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004845 if (is_single_device_type_equal(&out->device_list,
4846 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004847 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004848 !audio_extn_passthru_is_passthrough_stream(out) &&
4849 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004850 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004851 }
4852 /*
4853 * When A2DP is disconnected the
4854 * music playback is paused and the policy manager sends routing=0
4855 * But the audioflinger continues to write data until standby time
4856 * (3sec). As BT is turned off, the write gets blocked.
4857 * Avoid this by routing audio to speaker until standby.
4858 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004859 if (is_a2dp_out_device_type(&out->device_list) &&
4860 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004861 !audio_extn_a2dp_source_is_ready() &&
4862 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004863 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004864 }
4865 /*
4866 * When USB headset is disconnected the music platback paused
4867 * and the policy manager send routing=0. But if the USB is connected
4868 * back before the standby time, AFE is not closed and opened
4869 * when USB is connected back. So routing to speker will guarantee
4870 * AFE reconfiguration and AFE will be opend once USB is connected again
4871 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004872 if (is_usb_out_device_type(&out->device_list) &&
4873 list_empty(&new_devices) &&
4874 !audio_extn_usb_connected(NULL)) {
4875 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4876 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004877 /* To avoid a2dp to sco overlapping / BT device improper state
4878 * check with BT lib about a2dp streaming support before routing
4879 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004880 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004881 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004882 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4883 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004884 //combo usecase just by pass a2dp
4885 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4886 bypass_a2dp = true;
4887 } else {
4888 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4889 /* update device to a2dp and don't route as BT returned error
4890 * However it is still possible a2dp routing called because
4891 * of current active device disconnection (like wired headset)
4892 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004893 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004894 pthread_mutex_unlock(&adev->lock);
4895 pthread_mutex_unlock(&out->lock);
4896 goto error;
4897 }
4898 }
4899 }
4900
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004901 // Workaround: If routing to an non existing usb device, fail gracefully
4902 // The routing request will otherwise block during 10 second
4903 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004904 if (is_usb_out_device_type(&new_devices)) {
4905 struct str_parms *parms =
4906 str_parms_create_str(get_usb_device_address(&new_devices));
4907 if (!parms)
4908 goto error;
4909 if ((card = get_alive_usb_card(parms)) >= 0) {
4910 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4911 pthread_mutex_unlock(&adev->lock);
4912 pthread_mutex_unlock(&out->lock);
4913 str_parms_destroy(parms);
4914 ret = -ENOSYS;
4915 goto error;
4916 }
4917 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004918 }
4919
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004920 // Workaround: If routing to an non existing hdmi device, fail gracefully
4921 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4922 (platform_get_edid_info_v2(adev->platform,
4923 out->extconn.cs.controller,
4924 out->extconn.cs.stream) != 0)) {
4925 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4926 pthread_mutex_unlock(&adev->lock);
4927 pthread_mutex_unlock(&out->lock);
4928 ret = -ENOSYS;
4929 goto error;
4930 }
4931
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004932 /*
4933 * select_devices() call below switches all the usecases on the same
4934 * backend to the new device. Refer to check_usecases_codec_backend() in
4935 * the select_devices(). But how do we undo this?
4936 *
4937 * For example, music playback is active on headset (deep-buffer usecase)
4938 * and if we go to ringtones and select a ringtone, low-latency usecase
4939 * will be started on headset+speaker. As we can't enable headset+speaker
4940 * and headset devices at the same time, select_devices() switches the music
4941 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4942 * So when the ringtone playback is completed, how do we undo the same?
4943 *
4944 * We are relying on the out_set_parameters() call on deep-buffer output,
4945 * once the ringtone playback is ended.
4946 * NOTE: We should not check if the current devices are same as new devices.
4947 * Because select_devices() must be called to switch back the music
4948 * playback to headset.
4949 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004950 if (!list_empty(&new_devices)) {
4951 bool same_dev = compare_devices(&out->device_list, &new_devices);
4952 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004953
4954 if (output_drives_call(adev, out)) {
4955 if (!voice_is_call_state_active(adev)) {
4956 if (adev->mode == AUDIO_MODE_IN_CALL) {
4957 adev->current_call_output = out;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004958 ret = voice_start_call(adev);
4959 }
4960 } else {
4961 adev->current_call_output = out;
4962 voice_update_devices_for_all_voice_usecases(adev);
4963 }
4964 }
4965
Mingshu Pang60536d72020-09-09 15:28:22 +08004966 if (is_usb_out_device_type(&out->device_list)) {
4967 service_interval = audio_extn_usb_find_service_interval(false, true /*playback*/);
4968 audio_extn_usb_set_service_interval(true /*playback*/,
4969 service_interval,
4970 &reconfig);
4971 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4972 }
4973
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004974 if (!out->standby) {
4975 if (!same_dev) {
4976 ALOGV("update routing change");
4977 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4978 adev->perf_lock_opts,
4979 adev->perf_lock_opts_size);
4980 if (adev->adm_on_routing_change)
4981 adev->adm_on_routing_change(adev->adm_data,
4982 out->handle);
4983 }
4984 if (!bypass_a2dp) {
4985 select_devices(adev, out->usecase);
4986 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004987 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4988 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004989 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004990 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004991 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004992 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004993 }
4994
4995 if (!same_dev) {
4996 // on device switch force swap, lower functions will make sure
4997 // to check if swap is allowed or not.
4998 platform_set_swap_channels(adev, true);
4999 audio_extn_perf_lock_release(&adev->perf_lock_handle);
5000 }
Zhou Song1f93fa52020-11-20 13:57:39 +08005001 pthread_mutex_lock(&out->latch_lock);
5002 if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) {
5003 if (out->a2dp_muted) {
5004 out->a2dp_muted = false;
5005 if (is_offload_usecase(out->usecase))
5006 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5007 else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP)
5008 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005009 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005010 }
Zhou Song1f93fa52020-11-20 13:57:39 +08005011 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted)
5012 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
5013 pthread_mutex_unlock(&out->latch_lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005014 }
5015 }
5016
5017 pthread_mutex_unlock(&adev->lock);
5018 pthread_mutex_unlock(&out->lock);
5019
5020 /*handles device and call state changes*/
5021 audio_extn_extspk_update(adev->extspk);
5022
5023error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005024 ALOGV("%s: exit: code(%d)", __func__, ret);
5025 return ret;
5026}
5027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
5029{
5030 struct stream_out *out = (struct stream_out *)stream;
5031 struct audio_device *adev = out->dev;
5032 struct str_parms *parms;
5033 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07005034 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005035 int ext_controller = -1;
5036 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037
sangwoobc677242013-08-08 16:53:43 +09005038 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005039 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305041 if (!parms)
5042 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005043
5044 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5045 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005046 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005047 out->extconn.cs.controller = ext_controller;
5048 out->extconn.cs.stream = ext_stream;
5049 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5050 use_case_table[out->usecase], out->extconn.cs.controller,
5051 out->extconn.cs.stream);
5052 }
5053
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005054 if (out == adev->primary_output) {
5055 pthread_mutex_lock(&adev->lock);
5056 audio_extn_set_parameters(adev, parms);
5057 pthread_mutex_unlock(&adev->lock);
5058 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005059 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005060 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005061 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005062
5063 audio_extn_dts_create_state_notifier_node(out->usecase);
5064 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5065 popcount(out->channel_mask),
5066 out->playback_started);
5067
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005068 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005069 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005070
Surendar Karkaf51b5842018-04-26 11:28:38 +05305071 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5072 sizeof(value));
5073 if (err >= 0) {
5074 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5075 audio_extn_send_dual_mono_mixing_coefficients(out);
5076 }
5077
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305078 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5079 if (err >= 0) {
5080 strlcpy(out->profile, value, sizeof(out->profile));
5081 ALOGV("updating stream profile with value '%s'", out->profile);
5082 lock_output_stream(out);
5083 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5084 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005085 &out->device_list, out->flags,
5086 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305087 out->sample_rate, out->bit_width,
5088 out->channel_mask, out->profile,
5089 &out->app_type_cfg);
5090 pthread_mutex_unlock(&out->lock);
5091 }
5092
Alexy Joseph98988832017-01-13 14:56:59 -08005093 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005094 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5095 // and vendor.audio.hal.output.suspend.supported is set to true
5096 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005097 //check suspend parameter only for low latency and if the property
5098 //is enabled
5099 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5100 ALOGI("%s: got suspend_playback %s", __func__, value);
5101 lock_output_stream(out);
5102 if (!strncmp(value, "false", 5)) {
5103 //suspend_playback=false is supposed to set QOS value back to 75%
5104 //the mixer control sent with value Enable will achieve that
5105 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5106 } else if (!strncmp (value, "true", 4)) {
5107 //suspend_playback=true is supposed to remove QOS value
5108 //resetting the mixer control will set the default value
5109 //for the mixer control which is Disable and this removes the QOS vote
5110 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5111 } else {
5112 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5113 " got %s", __func__, value);
5114 ret = -1;
5115 }
5116
5117 if (ret != 0) {
5118 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5119 __func__, out->pm_qos_mixer_path, ret);
5120 }
5121
5122 pthread_mutex_unlock(&out->lock);
5123 }
5124 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005125
Alexy Joseph98988832017-01-13 14:56:59 -08005126 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305128error:
Eric Laurent994a6932013-07-17 11:51:42 -07005129 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130 return ret;
5131}
5132
Paul McLeana50b7332018-12-17 08:24:21 -07005133static int in_set_microphone_direction(const struct audio_stream_in *stream,
5134 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005135 struct stream_in *in = (struct stream_in *)stream;
5136
5137 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5138
5139 in->direction = dir;
5140
5141 if (in->standby)
5142 return 0;
5143
5144 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005145}
5146
5147static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005148 struct stream_in *in = (struct stream_in *)stream;
5149
5150 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5151
5152 if (zoom > 1.0 || zoom < -1.0)
5153 return -EINVAL;
5154
5155 in->zoom = zoom;
5156
5157 if (in->standby)
5158 return 0;
5159
5160 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005161}
5162
5163
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005164static bool stream_get_parameter_channels(struct str_parms *query,
5165 struct str_parms *reply,
5166 audio_channel_mask_t *supported_channel_masks) {
5167 int ret = -1;
5168 char value[512];
5169 bool first = true;
5170 size_t i, j;
5171
5172 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5173 ret = 0;
5174 value[0] = '\0';
5175 i = 0;
5176 while (supported_channel_masks[i] != 0) {
5177 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5178 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5179 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305180 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005181
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305182 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005183 first = false;
5184 break;
5185 }
5186 }
5187 i++;
5188 }
5189 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5190 }
5191 return ret == 0;
5192}
5193
5194static bool stream_get_parameter_formats(struct str_parms *query,
5195 struct str_parms *reply,
5196 audio_format_t *supported_formats) {
5197 int ret = -1;
5198 char value[256];
5199 size_t i, j;
5200 bool first = true;
5201
5202 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5203 ret = 0;
5204 value[0] = '\0';
5205 i = 0;
5206 while (supported_formats[i] != 0) {
5207 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5208 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5209 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305210 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005211 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305212 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005213 first = false;
5214 break;
5215 }
5216 }
5217 i++;
5218 }
5219 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5220 }
5221 return ret == 0;
5222}
5223
5224static bool stream_get_parameter_rates(struct str_parms *query,
5225 struct str_parms *reply,
5226 uint32_t *supported_sample_rates) {
5227
5228 int i;
5229 char value[256];
5230 int ret = -1;
5231 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5232 ret = 0;
5233 value[0] = '\0';
5234 i=0;
5235 int cursor = 0;
5236 while (supported_sample_rates[i]) {
5237 int avail = sizeof(value) - cursor;
5238 ret = snprintf(value + cursor, avail, "%s%d",
5239 cursor > 0 ? "|" : "",
5240 supported_sample_rates[i]);
5241 if (ret < 0 || ret >= avail) {
5242 // if cursor is at the last element of the array
5243 // overwrite with \0 is duplicate work as
5244 // snprintf already put a \0 in place.
5245 // else
5246 // we had space to write the '|' at value[cursor]
5247 // (which will be overwritten) or no space to fill
5248 // the first element (=> cursor == 0)
5249 value[cursor] = '\0';
5250 break;
5251 }
5252 cursor += ret;
5253 ++i;
5254 }
5255 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5256 value);
5257 }
5258 return ret >= 0;
5259}
5260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5262{
5263 struct stream_out *out = (struct stream_out *)stream;
5264 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005265 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266 char value[256];
5267 struct str_parms *reply = str_parms_create();
5268 size_t i, j;
5269 int ret;
5270 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005271
5272 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005273 if (reply) {
5274 str_parms_destroy(reply);
5275 }
5276 if (query) {
5277 str_parms_destroy(query);
5278 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005279 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5280 return NULL;
5281 }
5282
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005283 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005284 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5285 if (ret >= 0) {
5286 value[0] = '\0';
5287 i = 0;
5288 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005289 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5290 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005292 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005294 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295 first = false;
5296 break;
5297 }
5298 }
5299 i++;
5300 }
5301 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5302 str = str_parms_to_str(reply);
5303 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005304 voice_extn_out_get_parameters(out, query, reply);
5305 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005307
Alexy Joseph62142aa2015-11-16 15:10:34 -08005308
5309 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5310 if (ret >= 0) {
5311 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305312 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5313 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005314 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305315 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005316 } else {
5317 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305318 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005319 }
5320 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005321 if (str)
5322 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005323 str = str_parms_to_str(reply);
5324 }
5325
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005326 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5327 if (ret >= 0) {
5328 value[0] = '\0';
5329 i = 0;
5330 first = true;
5331 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005332 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5333 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005334 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005335 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005336 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005337 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005338 first = false;
5339 break;
5340 }
5341 }
5342 i++;
5343 }
5344 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005345 if (str)
5346 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005347 str = str_parms_to_str(reply);
5348 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005349
5350 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5351 if (ret >= 0) {
5352 value[0] = '\0';
5353 i = 0;
5354 first = true;
5355 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005356 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5357 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005358 if (!first) {
5359 strlcat(value, "|", sizeof(value));
5360 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005361 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005362 first = false;
5363 break;
5364 }
5365 }
5366 i++;
5367 }
5368 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5369 if (str)
5370 free(str);
5371 str = str_parms_to_str(reply);
5372 }
5373
Alexy Joseph98988832017-01-13 14:56:59 -08005374 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5375 //only low latency track supports suspend_resume
5376 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005377 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005378 if (str)
5379 free(str);
5380 str = str_parms_to_str(reply);
5381 }
5382
5383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 str_parms_destroy(query);
5385 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005386 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387 return str;
5388}
5389
5390static uint32_t out_get_latency(const struct audio_stream_out *stream)
5391{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005392 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005393 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005394 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395
Alexy Josephaa54c872014-12-03 02:46:47 -08005396 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305397 lock_output_stream(out);
5398 latency = audio_extn_utils_compress_get_dsp_latency(out);
5399 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005400 } else if ((out->realtime) ||
5401 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005402 // since the buffer won't be filled up faster than realtime,
5403 // return a smaller number
5404 if (out->config.rate)
5405 period_ms = (out->af_period_multiplier * out->config.period_size *
5406 1000) / (out->config.rate);
5407 else
5408 period_ms = 0;
George Gao9ba8a142020-07-23 14:30:03 -07005409 latency = period_ms + platform_render_latency(out) / 1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005410 } else {
5411 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005412 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005413 }
5414
Zhou Songd2537a02020-06-11 22:04:46 +08005415 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005416 latency += audio_extn_a2dp_get_encoder_latency();
5417
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305418 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005419 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420}
5421
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305422static float AmpToDb(float amplification)
5423{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305424 float db = DSD_VOLUME_MIN_DB;
5425 if (amplification > 0) {
5426 db = 20 * log10(amplification);
5427 if(db < DSD_VOLUME_MIN_DB)
5428 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305429 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305430 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305431}
5432
Arun Mirpuri5d170872019-03-26 13:21:31 -07005433static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5434 float right)
5435{
5436 struct stream_out *out = (struct stream_out *)stream;
5437 long volume = 0;
5438 char mixer_ctl_name[128] = "";
5439 struct audio_device *adev = out->dev;
5440 struct mixer_ctl *ctl = NULL;
5441 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5442 PCM_PLAYBACK);
5443
5444 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5445 "Playback %d Volume", pcm_device_id);
5446 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5447 if (!ctl) {
5448 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5449 __func__, mixer_ctl_name);
5450 return -EINVAL;
5451 }
5452 if (left != right)
5453 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5454 __func__, left, right);
5455 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5456 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5457 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5458 __func__, mixer_ctl_name, volume);
5459 return -EINVAL;
5460 }
5461 return 0;
5462}
5463
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305464static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5465 float right)
5466{
5467 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305468 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305469 char mixer_ctl_name[128];
5470 struct audio_device *adev = out->dev;
5471 struct mixer_ctl *ctl;
5472 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5473 PCM_PLAYBACK);
5474
5475 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5476 "Compress Playback %d Volume", pcm_device_id);
5477 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5478 if (!ctl) {
5479 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5480 __func__, mixer_ctl_name);
5481 return -EINVAL;
5482 }
5483 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5484 __func__, mixer_ctl_name, left, right);
5485 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5486 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5487 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5488
5489 return 0;
5490}
5491
Zhou Song2b8f28f2017-09-11 10:51:38 +08005492static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5493 float right)
5494{
5495 struct stream_out *out = (struct stream_out *)stream;
5496 char mixer_ctl_name[] = "App Type Gain";
5497 struct audio_device *adev = out->dev;
5498 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305499 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005500
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005501 if (!is_valid_volume(left, right)) {
5502 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5503 __func__, left, right);
5504 return -EINVAL;
5505 }
5506
Zhou Song2b8f28f2017-09-11 10:51:38 +08005507 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5508 if (!ctl) {
5509 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5510 __func__, mixer_ctl_name);
5511 return -EINVAL;
5512 }
5513
5514 set_values[0] = 0; //0: Rx Session 1:Tx Session
5515 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305516 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5517 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005518
5519 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5520 return 0;
5521}
5522
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305523static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5524 float right)
5525{
5526 struct stream_out *out = (struct stream_out *)stream;
5527 /* Volume control for pcm playback */
5528 if (left != right) {
5529 return -EINVAL;
5530 } else {
5531 char mixer_ctl_name[128];
5532 struct audio_device *adev = out->dev;
5533 struct mixer_ctl *ctl;
5534 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5535 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5536 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5537 if (!ctl) {
5538 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5539 return -EINVAL;
5540 }
5541
5542 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5543 int ret = mixer_ctl_set_value(ctl, 0, volume);
5544 if (ret < 0) {
5545 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5546 return -EINVAL;
5547 }
5548
5549 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5550
5551 return 0;
5552 }
5553}
5554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555static int out_set_volume(struct audio_stream_out *stream, float left,
5556 float right)
5557{
Eric Laurenta9024de2013-04-04 09:19:12 -07005558 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005559 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305560 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005561
Arun Mirpuri5d170872019-03-26 13:21:31 -07005562 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005563 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5564 /* only take left channel into account: the API is for stereo anyway */
5565 out->muted = (left == 0.0f);
5566 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005567 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305568 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005569 /*
5570 * Set mute or umute on HDMI passthrough stream.
5571 * Only take left channel into account.
5572 * Mute is 0 and unmute 1
5573 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305574 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305575 } else if (out->format == AUDIO_FORMAT_DSD){
5576 char mixer_ctl_name[128] = "DSD Volume";
5577 struct audio_device *adev = out->dev;
5578 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5579
5580 if (!ctl) {
5581 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5582 __func__, mixer_ctl_name);
5583 return -EINVAL;
5584 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305585 volume[0] = (long)(AmpToDb(left));
5586 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305587 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5588 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005589 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005590 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005591 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5592 struct listnode *node = NULL;
5593 list_for_each(node, &adev->active_outputs_list) {
5594 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5595 streams_output_ctxt_t,
5596 list);
5597 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5598 out->volume_l = out_ctxt->output->volume_l;
5599 out->volume_r = out_ctxt->output->volume_r;
5600 }
5601 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005602 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005603 if (!out->a2dp_muted) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005604 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5605 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005606 pthread_mutex_unlock(&out->latch_lock);
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005607 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005608 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005609 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08005610 ALOGV("%s: compress mute %d", __func__, out->a2dp_muted);
5611 if (!out->a2dp_muted)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305612 ret = out_set_compr_volume(stream, left, right);
5613 out->volume_l = left;
5614 out->volume_r = right;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08005615 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305616 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005617 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005618 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005619 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5620 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song1f93fa52020-11-20 13:57:39 +08005621 pthread_mutex_lock(&out->latch_lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08005622 if (!out->standby) {
5623 audio_extn_utils_send_app_type_gain(out->dev,
5624 out->app_type_cfg.app_type,
5625 &out->app_type_cfg.gain[0]);
Zhou Song1f93fa52020-11-20 13:57:39 +08005626 if (!out->a2dp_muted)
5627 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005628 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005629 out->volume_l = left;
5630 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005631 pthread_mutex_unlock(&out->latch_lock);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005632 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005633 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5634 ALOGV("%s: MMAP set volume called", __func__);
5635 if (!out->standby)
5636 ret = out_set_mmap_volume(stream, left, right);
5637 out->volume_l = left;
5638 out->volume_r = right;
5639 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305640 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305641 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5642 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Zhou Song1f93fa52020-11-20 13:57:39 +08005643 pthread_mutex_lock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305644 /* Volume control for pcm playback */
Zhou Song1f93fa52020-11-20 13:57:39 +08005645 if (!out->standby && !out->a2dp_muted)
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305646 ret = out_set_pcm_volume(stream, left, right);
5647 else
5648 out->apply_volume = true;
5649
5650 out->volume_l = left;
5651 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005652 pthread_mutex_unlock(&out->latch_lock);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305653 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005654 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5655 ALOGV("%s: bus device set volume called", __func__);
Zhou Song1f93fa52020-11-20 13:57:39 +08005656 pthread_mutex_lock(&out->latch_lock);
5657 if (!out->standby && !out->a2dp_muted)
Derek Chenf13dd492018-11-13 14:53:51 -08005658 ret = out_set_pcm_volume(stream, left, right);
5659 out->volume_l = left;
5660 out->volume_r = right;
Zhou Song1f93fa52020-11-20 13:57:39 +08005661 pthread_mutex_unlock(&out->latch_lock);
Derek Chenf13dd492018-11-13 14:53:51 -08005662 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005663 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665 return -ENOSYS;
5666}
5667
Zhou Songc9672822017-08-16 16:01:39 +08005668static void update_frames_written(struct stream_out *out, size_t bytes)
5669{
5670 size_t bpf = 0;
5671
5672 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5673 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5674 bpf = 1;
5675 else if (!is_offload_usecase(out->usecase))
5676 bpf = audio_bytes_per_sample(out->format) *
5677 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005678
5679 pthread_mutex_lock(&out->position_query_lock);
5680 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005681 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005682 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5683 }
5684 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005685}
5686
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005687int split_and_write_audio_haptic_data(struct stream_out *out,
5688 const void *buffer, size_t bytes_to_write)
5689{
5690 struct audio_device *adev = out->dev;
5691
5692 int ret = 0;
5693 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5694 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5695 size_t frame_size = channel_count * bytes_per_sample;
5696 size_t frame_count = bytes_to_write / frame_size;
5697
5698 bool force_haptic_path =
5699 property_get_bool("vendor.audio.test_haptic", false);
5700
5701 // extract Haptics data from Audio buffer
5702 bool alloc_haptic_buffer = false;
5703 int haptic_channel_count = adev->haptics_config.channels;
5704 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5705 size_t audio_frame_size = frame_size - haptic_frame_size;
5706 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5707
5708 if (adev->haptic_buffer == NULL) {
5709 alloc_haptic_buffer = true;
5710 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5711 free(adev->haptic_buffer);
5712 adev->haptic_buffer_size = 0;
5713 alloc_haptic_buffer = true;
5714 }
5715
5716 if (alloc_haptic_buffer) {
5717 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005718 if(adev->haptic_buffer == NULL) {
5719 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5720 return -ENOMEM;
5721 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005722 adev->haptic_buffer_size = total_haptic_buffer_size;
5723 }
5724
5725 size_t src_index = 0, aud_index = 0, hap_index = 0;
5726 uint8_t *audio_buffer = (uint8_t *)buffer;
5727 uint8_t *haptic_buffer = adev->haptic_buffer;
5728
5729 // This is required for testing only. This works for stereo data only.
5730 // One channel is fed to audio stream and other to haptic stream for testing.
5731 if (force_haptic_path)
5732 audio_frame_size = haptic_frame_size = bytes_per_sample;
5733
5734 for (size_t i = 0; i < frame_count; i++) {
5735 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5736 audio_frame_size);
5737 aud_index += audio_frame_size;
5738 src_index += audio_frame_size;
5739
5740 if (adev->haptic_pcm)
5741 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5742 haptic_frame_size);
5743 hap_index += haptic_frame_size;
5744 src_index += haptic_frame_size;
5745
5746 // This is required for testing only.
5747 // Discard haptic channel data.
5748 if (force_haptic_path)
5749 src_index += haptic_frame_size;
5750 }
5751
5752 // write to audio pipeline
5753 ret = pcm_write(out->pcm, (void *)audio_buffer,
5754 frame_count * audio_frame_size);
5755
5756 // write to haptics pipeline
5757 if (adev->haptic_pcm)
5758 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5759 frame_count * haptic_frame_size);
5760
5761 return ret;
5762}
5763
Aalique Grahame22e49102018-12-18 14:23:57 -08005764#ifdef NO_AUDIO_OUT
5765static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5766 const void *buffer __unused, size_t bytes)
5767{
5768 struct stream_out *out = (struct stream_out *)stream;
5769
5770 /* No Output device supported other than BT for playback.
5771 * Sleep for the amount of buffer duration
5772 */
5773 lock_output_stream(out);
5774 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5775 (const struct audio_stream_out *)&out->stream) /
5776 out_get_sample_rate(&out->stream.common));
5777 pthread_mutex_unlock(&out->lock);
5778 return bytes;
5779}
5780#endif
5781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5783 size_t bytes)
5784{
5785 struct stream_out *out = (struct stream_out *)stream;
5786 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005787 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305788 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005789 const size_t frame_size = audio_stream_out_frame_size(stream);
5790 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305791 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005792 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793
Haynes Mathew George380745d2017-10-04 15:27:45 -07005794 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005795 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305796
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305797 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005798
Dhananjay Kumarac341582017-02-23 23:42:25 +05305799 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305800 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305801 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5802 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005803 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305804 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305805 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305806 ALOGD(" %s: sound card is not active/SSR state", __func__);
5807 ret= -EIO;
5808 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305809 }
5810 }
5811
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305812 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305813 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305814 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305815 goto exit;
5816 }
5817
Haynes Mathew George16081042017-05-31 17:16:49 -07005818 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5819 ret = -EINVAL;
5820 goto exit;
5821 }
5822
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005823 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305824 !out->is_iec61937_info_available) {
5825
5826 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5827 out->is_iec61937_info_available = true;
5828 } else if (audio_extn_passthru_is_enabled()) {
5829 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305830 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305831
5832 if((out->format == AUDIO_FORMAT_DTS) ||
5833 (out->format == AUDIO_FORMAT_DTS_HD)) {
5834 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5835 buffer, bytes);
5836 if (ret) {
5837 if (ret != -ENOSYS) {
5838 out->is_iec61937_info_available = false;
5839 ALOGD("iec61937 transmission info not yet updated retry");
5840 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305841 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305842 /* if stream has started and after that there is
5843 * stream config change (iec transmission config)
5844 * then trigger select_device to update backend configuration.
5845 */
5846 out->stream_config_changed = true;
5847 pthread_mutex_lock(&adev->lock);
5848 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305849 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005850 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305851 ret = -EINVAL;
5852 goto exit;
5853 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305854 pthread_mutex_unlock(&adev->lock);
5855 out->stream_config_changed = false;
5856 out->is_iec61937_info_available = true;
5857 }
5858 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305859
Meng Wang4c32fb42020-01-16 17:57:11 +08005860#ifdef AUDIO_GKI_ENABLED
5861 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5862 compr_passthr = out->compr_config.codec->reserved[0];
5863#else
5864 compr_passthr = out->compr_config.codec->compr_passthr;
5865#endif
5866
Garmond Leung317cbf12017-09-13 16:20:50 -07005867 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005868 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305869 (out->is_iec61937_info_available == true)) {
5870 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5871 ret = -EINVAL;
5872 goto exit;
5873 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305874 }
5875 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305876
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005877 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005878 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005879 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5880 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Zhou Song9ebf6792020-09-23 22:49:01 +08005881 if (!is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305882 ret = -EIO;
5883 goto exit;
5884 }
5885 }
5886 }
5887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005888 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005889 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005890 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5891
Eric Laurent150dbfe2013-02-27 14:31:02 -08005892 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005893 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5894 ret = voice_extn_compress_voip_start_output_stream(out);
5895 else
5896 ret = start_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005897 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005898 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005899 out->standby = true;
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005900 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005901 goto exit;
5902 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305903 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005904 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005905
5906 if ((last_known_cal_step != -1) && (adev->platform != NULL)) {
vivek mehtab72d08d2016-04-29 03:16:47 -07005907 ALOGD("%s: retry previous failed cal level set", __func__);
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005908 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305909 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005910 }
Weiyin Jiangac2bae82020-07-29 17:23:53 +08005911 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305912
5913 if ((out->is_iec61937_info_available == true) &&
5914 (audio_extn_passthru_is_passthrough_stream(out))&&
5915 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5916 ret = -EINVAL;
5917 goto exit;
5918 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305919 if (out->set_dual_mono)
5920 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005921
5922 // log startup time in ms.
5923 simple_stats_log(
5924 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005926
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005927 if (adev->is_channel_status_set == false &&
5928 compare_device_type(&out->device_list,
5929 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005930 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305931 adev->is_channel_status_set = true;
5932 }
5933
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305934 if ((adev->use_old_pspd_mix_ctrl == true) &&
5935 (out->pspd_coeff_sent == false)) {
5936 /*
5937 * Need to resend pspd coefficients after stream started for
5938 * older kernel version as it does not save the coefficients
5939 * and also stream has to be started for coeff to apply.
5940 */
5941 usecase = get_usecase_from_list(adev, out->usecase);
5942 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305943 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305944 out->pspd_coeff_sent = true;
5945 }
5946 }
5947
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005948 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005949 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005950 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005951 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005952 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5953 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305954 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5955 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005956 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305957 out->send_next_track_params = false;
5958 out->is_compr_metadata_avail = false;
5959 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005960 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305961 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305962 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005963
Ashish Jain83a6cc22016-06-28 14:34:17 +05305964 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305965 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305966 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305967 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005968 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305969 return -EINVAL;
5970 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305971 audio_format_t dst_format = out->hal_op_format;
5972 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305973
Dieter Luecking5d57def2018-09-07 14:23:37 +02005974 /* prevent division-by-zero */
5975 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5976 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5977 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5978 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305979 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005980 ATRACE_END();
5981 return -EINVAL;
5982 }
5983
Ashish Jainf1eaa582016-05-23 20:54:24 +05305984 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5985 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5986
Ashish Jain83a6cc22016-06-28 14:34:17 +05305987 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305988 dst_format,
5989 buffer,
5990 src_format,
5991 frames);
5992
Ashish Jain83a6cc22016-06-28 14:34:17 +05305993 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305994 bytes_to_write);
5995
5996 /*Convert written bytes in audio flinger format*/
5997 if (ret > 0)
5998 ret = ((ret * format_to_bitwidth_table[out->format]) /
5999 format_to_bitwidth_table[dst_format]);
6000 }
6001 } else
6002 ret = compress_write(out->compr, buffer, bytes);
6003
Zhou Songc9672822017-08-16 16:01:39 +08006004 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
6005 update_frames_written(out, bytes);
6006
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306007 if (ret < 0)
6008 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08006009 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05306010 /*msg to cb thread only if non blocking write is enabled*/
6011 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05306012 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05306014 } else if (-ENETRESET == ret) {
6015 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306016 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05306017 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05306018 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006019 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05306020 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006021 }
Ashish Jain5106d362016-05-11 19:23:33 +05306022
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05306023 /* Call compr start only when non-zero bytes of data is there to be rendered */
6024 if (!out->playback_started && ret > 0) {
6025 int status = compress_start(out->compr);
6026 if (status < 0) {
6027 ret = status;
6028 ALOGE("%s: compr start failed with err %d", __func__, errno);
6029 goto exit;
6030 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07006031 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006032 out->playback_started = 1;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006033 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006034 out->offload_state = OFFLOAD_STATE_PLAYING;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006035 pthread_mutex_unlock(&out->latch_lock);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006036
6037 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6038 popcount(out->channel_mask),
6039 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006040 }
6041 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006042 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006043 return ret;
6044 } else {
6045 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006046 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006047 if (out->muted)
6048 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006049 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6050 __func__, frames, frame_size, bytes_to_write);
6051
Aalique Grahame22e49102018-12-18 14:23:57 -08006052 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006053 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6054 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6055 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006056 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6057 int16_t *src = (int16_t *)buffer;
6058 int16_t *dst = (int16_t *)buffer;
6059
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006060 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006061 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006062 "out_write called for %s use case with wrong properties",
6063 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006064
6065 /*
6066 * FIXME: this can be removed once audio flinger mixer supports
6067 * mono output
6068 */
6069
6070 /*
6071 * Code below goes over each frame in the buffer and adds both
6072 * L and R samples and then divides by 2 to convert to mono
6073 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006074 if (channel_count == 2) {
6075 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6076 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6077 }
6078 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006079 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006080 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006081
6082 // Note: since out_get_presentation_position() is called alternating with out_write()
6083 // by AudioFlinger, we can check underruns using the prior timestamp read.
6084 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6085 if (out->last_fifo_valid) {
6086 // compute drain to see if there is an underrun.
6087 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306088 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6089 int64_t frames_by_time =
6090 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6091 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006092 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6093
6094 if (underrun > 0) {
6095 simple_stats_log(&out->fifo_underruns, underrun);
6096
6097 ALOGW("%s: underrun(%lld) "
6098 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6099 __func__,
6100 (long long)out->fifo_underruns.n,
6101 (long long)frames_by_time,
6102 (long long)out->last_fifo_frames_remaining);
6103 }
6104 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6105 }
6106
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306107 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006108
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006109 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006110
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006111 if (out->config.rate)
6112 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6113 out->config.rate;
6114
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006115 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006116 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6117
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006118 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006119 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006120 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306121 out->convert_buffer != NULL) {
6122
6123 memcpy_by_audio_format(out->convert_buffer,
6124 out->hal_op_format,
6125 buffer,
6126 out->hal_ip_format,
6127 out->config.period_size * out->config.channels);
6128
6129 ret = pcm_write(out->pcm, out->convert_buffer,
6130 (out->config.period_size *
6131 out->config.channels *
6132 format_to_bitwidth_table[out->hal_op_format]));
6133 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306134 /*
6135 * To avoid underrun in DSP when the application is not pumping
6136 * data at required rate, check for the no. of bytes and ignore
6137 * pcm_write if it is less than actual buffer size.
6138 * It is a work around to a change in compress VOIP driver.
6139 */
6140 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6141 bytes < (out->config.period_size * out->config.channels *
6142 audio_bytes_per_sample(out->format))) {
6143 size_t voip_buf_size =
6144 out->config.period_size * out->config.channels *
6145 audio_bytes_per_sample(out->format);
6146 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6147 __func__, bytes, voip_buf_size);
6148 usleep(((uint64_t)voip_buf_size - bytes) *
6149 1000000 / audio_stream_out_frame_size(stream) /
6150 out_get_sample_rate(&out->stream.common));
6151 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006152 } else {
6153 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6154 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6155 else
6156 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6157 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306158 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006160 release_out_focus(out);
6161
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306162 if (ret < 0)
6163 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006164 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306165 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006166 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006167 }
6168
6169exit:
Zhou Songc9672822017-08-16 16:01:39 +08006170 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306171 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306172 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006174 pthread_mutex_unlock(&out->lock);
6175
6176 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006177 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006178 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306179 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306180 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306181 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306182 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306183 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306184 out->standby = true;
6185 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306186 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006187 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6188 /* prevent division-by-zero */
6189 uint32_t stream_size = audio_stream_out_frame_size(stream);
6190 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006191
Dieter Luecking5d57def2018-09-07 14:23:37 +02006192 if ((stream_size == 0) || (srate == 0)) {
6193 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6194 ATRACE_END();
6195 return -EINVAL;
6196 }
6197 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6198 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006199 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306200 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006201 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006202 return ret;
6203 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006204 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006205 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006206 return bytes;
6207}
6208
6209static int out_get_render_position(const struct audio_stream_out *stream,
6210 uint32_t *dsp_frames)
6211{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006212 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006213
6214 if (dsp_frames == NULL)
6215 return -EINVAL;
6216
6217 *dsp_frames = 0;
6218 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006219 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306220
6221 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6222 * this operation and adev_close_output_stream(where out gets reset).
6223 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306224 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006225 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306226 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006227 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306228 return 0;
6229 }
6230
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006231 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306232 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306233 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006234 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306235 if (ret < 0)
6236 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006237 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306238 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006239 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306240 if (-ENETRESET == ret) {
6241 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306242 out->card_status = CARD_STATUS_OFFLINE;
6243 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306244 } else if(ret < 0) {
6245 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306246 ret = -EINVAL;
6247 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306248 /*
6249 * Handle corner case where compress session is closed during SSR
6250 * and timestamp is queried
6251 */
6252 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306253 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306254 } else if (out->prev_card_status_offline) {
6255 ALOGE("ERROR: previously sound card was offline,return error");
6256 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306257 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306258 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006259 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306260 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306261 pthread_mutex_unlock(&out->lock);
6262 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006263 } else if (audio_is_linear_pcm(out->format)) {
6264 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006265 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006266 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006267 } else
6268 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006269}
6270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006271static int out_add_audio_effect(const struct audio_stream *stream __unused,
6272 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273{
6274 return 0;
6275}
6276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006277static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6278 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006279{
6280 return 0;
6281}
6282
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006283static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6284 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006285{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306286 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006287}
6288
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006289static int out_get_presentation_position(const struct audio_stream_out *stream,
6290 uint64_t *frames, struct timespec *timestamp)
6291{
6292 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306293 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006294 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006295
Ashish Jain5106d362016-05-11 19:23:33 +05306296 /* below piece of code is not guarded against any lock because audioFliner serializes
6297 * this operation and adev_close_output_stream( where out gets reset).
6298 */
6299 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306300 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006301 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306302 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6303 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6304 return 0;
6305 }
6306
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006307 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006308
Ashish Jain5106d362016-05-11 19:23:33 +05306309 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6310 ret = compress_get_tstamp(out->compr, &dsp_frames,
6311 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006312 // Adjustment accounts for A2dp encoder latency with offload usecases
6313 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006314 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006315 unsigned long offset =
6316 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6317 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6318 }
Ashish Jain5106d362016-05-11 19:23:33 +05306319 ALOGVV("%s rendered frames %ld sample_rate %d",
6320 __func__, dsp_frames, out->sample_rate);
6321 *frames = dsp_frames;
6322 if (ret < 0)
6323 ret = -errno;
6324 if (-ENETRESET == ret) {
6325 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306326 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306327 ret = -EINVAL;
6328 } else
6329 ret = 0;
6330 /* this is the best we can do */
6331 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006332 } else {
6333 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006334 unsigned int avail;
6335 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006336 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006337 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006338
Andy Hunga1f48fa2019-07-01 18:14:53 -07006339 if (out->kernel_buffer_size > avail) {
6340 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6341 } else {
6342 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6343 __func__, avail, out->kernel_buffer_size);
6344 avail = out->kernel_buffer_size;
6345 frames_temp = out->last_fifo_frames_remaining = 0;
6346 }
6347 out->last_fifo_valid = true;
6348 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6349
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006350 if (out->written >= frames_temp)
6351 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006352
Andy Hunga1f48fa2019-07-01 18:14:53 -07006353 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6354 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6355
Weiyin Jiangd4633762018-03-16 12:05:03 +08006356 // This adjustment accounts for buffering after app processor.
6357 // It is based on estimated DSP latency per use case, rather than exact.
George Gao9ba8a142020-07-23 14:30:03 -07006358 frames_temp = platform_render_latency(out) *
Robert Lee58215542019-07-15 20:55:12 +08006359 out->sample_rate / 1000000LL;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006360 if (signed_frames >= frames_temp)
6361 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006362
Weiyin Jiangd4633762018-03-16 12:05:03 +08006363 // Adjustment accounts for A2dp encoder latency with non offload usecases
6364 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006365 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006366 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6367 if (signed_frames >= frames_temp)
6368 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006369 }
6370
6371 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006372 *frames = signed_frames;
6373 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006374 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006375 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6376 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006377 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306378 *frames = out->written;
6379 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306380 if (is_offload_usecase(out->usecase))
6381 ret = -EINVAL;
6382 else
6383 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006384 }
6385 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006386 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006387 return ret;
6388}
6389
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006390static int out_set_callback(struct audio_stream_out *stream,
6391 stream_callback_t callback, void *cookie)
6392{
6393 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006394 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006395
6396 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006397 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006398 out->client_callback = callback;
6399 out->client_cookie = cookie;
6400 if (out->adsp_hdlr_stream_handle) {
6401 ret = audio_extn_adsp_hdlr_stream_set_callback(
6402 out->adsp_hdlr_stream_handle,
6403 callback,
6404 cookie);
6405 if (ret)
6406 ALOGW("%s:adsp hdlr callback registration failed %d",
6407 __func__, ret);
6408 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006409 pthread_mutex_unlock(&out->lock);
6410 return 0;
6411}
6412
6413static int out_pause(struct audio_stream_out* stream)
6414{
6415 struct stream_out *out = (struct stream_out *)stream;
6416 int status = -ENOSYS;
6417 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006418 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006419 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306420 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006421 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006422 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006423 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306424 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306425 status = compress_pause(out->compr);
6426
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006427 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006428
Mingming Yin21854652016-04-13 11:54:02 -07006429 if (audio_extn_passthru_is_active()) {
6430 ALOGV("offload use case, pause passthru");
6431 audio_extn_passthru_on_pause(out);
6432 }
6433
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306434 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006435 audio_extn_dts_notify_playback_state(out->usecase, 0,
6436 out->sample_rate, popcount(out->channel_mask),
6437 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006438 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006439 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006440 pthread_mutex_unlock(&out->lock);
6441 }
6442 return status;
6443}
6444
6445static int out_resume(struct audio_stream_out* stream)
6446{
6447 struct stream_out *out = (struct stream_out *)stream;
6448 int status = -ENOSYS;
6449 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006450 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006451 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306452 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006453 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006454 pthread_mutex_lock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006455 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306456 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306457 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006458 }
6459 if (!status) {
6460 out->offload_state = OFFLOAD_STATE_PLAYING;
6461 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306462 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006463 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6464 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006465 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006466 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006467 pthread_mutex_unlock(&out->lock);
6468 }
6469 return status;
6470}
6471
6472static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6473{
6474 struct stream_out *out = (struct stream_out *)stream;
6475 int status = -ENOSYS;
6476 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006477 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006478 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006479 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6480 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6481 else
6482 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6483 pthread_mutex_unlock(&out->lock);
6484 }
6485 return status;
6486}
6487
6488static int out_flush(struct audio_stream_out* stream)
6489{
6490 struct stream_out *out = (struct stream_out *)stream;
6491 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006492 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006493 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006494 lock_output_stream(out);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006495 pthread_mutex_lock(&out->latch_lock);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006496 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6497 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006498 } else {
6499 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6500 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006501 out->written = 0;
Weiyin Jiangd5974e62020-09-08 20:28:22 +08006502 pthread_mutex_unlock(&out->latch_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006503 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006504 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006505 return 0;
6506 }
6507 return -ENOSYS;
6508}
6509
Haynes Mathew George16081042017-05-31 17:16:49 -07006510static int out_stop(const struct audio_stream_out* stream)
6511{
6512 struct stream_out *out = (struct stream_out *)stream;
6513 struct audio_device *adev = out->dev;
6514 int ret = -ENOSYS;
6515
6516 ALOGV("%s", __func__);
6517 pthread_mutex_lock(&adev->lock);
6518 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6519 out->playback_started && out->pcm != NULL) {
6520 pcm_stop(out->pcm);
6521 ret = stop_output_stream(out);
6522 out->playback_started = false;
6523 }
6524 pthread_mutex_unlock(&adev->lock);
6525 return ret;
6526}
6527
6528static int out_start(const struct audio_stream_out* stream)
6529{
6530 struct stream_out *out = (struct stream_out *)stream;
6531 struct audio_device *adev = out->dev;
6532 int ret = -ENOSYS;
6533
6534 ALOGV("%s", __func__);
6535 pthread_mutex_lock(&adev->lock);
6536 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6537 !out->playback_started && out->pcm != NULL) {
6538 ret = start_output_stream(out);
6539 if (ret == 0) {
6540 out->playback_started = true;
6541 }
6542 }
6543 pthread_mutex_unlock(&adev->lock);
6544 return ret;
6545}
6546
6547/*
6548 * Modify config->period_count based on min_size_frames
6549 */
6550static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6551{
6552 int periodCountRequested = (min_size_frames + config->period_size - 1)
6553 / config->period_size;
6554 int periodCount = MMAP_PERIOD_COUNT_MIN;
6555
6556 ALOGV("%s original config.period_size = %d config.period_count = %d",
6557 __func__, config->period_size, config->period_count);
6558
6559 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6560 periodCount *= 2;
6561 }
6562 config->period_count = periodCount;
6563
6564 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6565}
6566
Phil Burkfe17efd2019-03-25 10:23:35 -07006567// Read offset for the positional timestamp from a persistent vendor property.
6568// This is to workaround apparent inaccuracies in the timing information that
6569// is used by the AAudio timing model. The inaccuracies can cause glitches.
6570static int64_t get_mmap_out_time_offset() {
6571 const int32_t kDefaultOffsetMicros = 0;
6572 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006573 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006574 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6575 return mmap_time_offset_micros * (int64_t)1000;
6576}
6577
Haynes Mathew George16081042017-05-31 17:16:49 -07006578static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6579 int32_t min_size_frames,
6580 struct audio_mmap_buffer_info *info)
6581{
6582 struct stream_out *out = (struct stream_out *)stream;
6583 struct audio_device *adev = out->dev;
6584 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006585 unsigned int offset1 = 0;
6586 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006587 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006588 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006589 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006590
Arun Mirpuri5d170872019-03-26 13:21:31 -07006591 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306592 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006593 pthread_mutex_lock(&adev->lock);
6594
Sharad Sanglec6f32552018-05-04 16:15:38 +05306595 if (CARD_STATUS_OFFLINE == out->card_status ||
6596 CARD_STATUS_OFFLINE == adev->card_status) {
6597 ALOGW("out->card_status or adev->card_status offline, try again");
6598 ret = -EIO;
6599 goto exit;
6600 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306601 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006602 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6603 ret = -EINVAL;
6604 goto exit;
6605 }
6606 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6607 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6608 ret = -ENOSYS;
6609 goto exit;
6610 }
6611 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6612 if (out->pcm_device_id < 0) {
6613 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6614 __func__, out->pcm_device_id, out->usecase);
6615 ret = -EINVAL;
6616 goto exit;
6617 }
6618
6619 adjust_mmap_period_count(&out->config, min_size_frames);
6620
Arun Mirpuri5d170872019-03-26 13:21:31 -07006621 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006622 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6623 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6624 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306625 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306626 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6627 out->card_status = CARD_STATUS_OFFLINE;
6628 adev->card_status = CARD_STATUS_OFFLINE;
6629 ret = -EIO;
6630 goto exit;
6631 }
6632
Haynes Mathew George16081042017-05-31 17:16:49 -07006633 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6634 step = "open";
6635 ret = -ENODEV;
6636 goto exit;
6637 }
6638 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6639 if (ret < 0) {
6640 step = "begin";
6641 goto exit;
6642 }
juyuchen626833d2019-06-04 16:48:02 +08006643
6644 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006645 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006646 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006647 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006648 ret = platform_get_mmap_data_fd(adev->platform,
6649 out->pcm_device_id, 0 /*playback*/,
6650 &info->shared_memory_fd,
6651 &mmap_size);
6652 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006653 // Fall back to non exclusive mode
6654 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6655 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006656 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6657 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6658
Arun Mirpuri5d170872019-03-26 13:21:31 -07006659 if (mmap_size < buffer_size) {
6660 step = "mmap";
6661 goto exit;
6662 }
juyuchen626833d2019-06-04 16:48:02 +08006663 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006664 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006665 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006666 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006667
6668 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6669 if (ret < 0) {
6670 step = "commit";
6671 goto exit;
6672 }
6673
Phil Burkfe17efd2019-03-25 10:23:35 -07006674 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6675
Haynes Mathew George16081042017-05-31 17:16:49 -07006676 out->standby = false;
6677 ret = 0;
6678
Arun Mirpuri5d170872019-03-26 13:21:31 -07006679 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006680 __func__, info->shared_memory_address, info->buffer_size_frames);
6681
6682exit:
6683 if (ret != 0) {
6684 if (out->pcm == NULL) {
6685 ALOGE("%s: %s - %d", __func__, step, ret);
6686 } else {
6687 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6688 pcm_close(out->pcm);
6689 out->pcm = NULL;
6690 }
6691 }
6692 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306693 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006694 return ret;
6695}
6696
6697static int out_get_mmap_position(const struct audio_stream_out *stream,
6698 struct audio_mmap_position *position)
6699{
6700 struct stream_out *out = (struct stream_out *)stream;
6701 ALOGVV("%s", __func__);
6702 if (position == NULL) {
6703 return -EINVAL;
6704 }
6705 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006706 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006707 return -ENOSYS;
6708 }
6709 if (out->pcm == NULL) {
6710 return -ENOSYS;
6711 }
6712
6713 struct timespec ts = { 0, 0 };
6714 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6715 if (ret < 0) {
6716 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6717 return ret;
6718 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006719 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6720 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006721 return 0;
6722}
6723
6724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006725/** audio_stream_in implementation **/
6726static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6727{
6728 struct stream_in *in = (struct stream_in *)stream;
6729
6730 return in->config.rate;
6731}
6732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006733static int in_set_sample_rate(struct audio_stream *stream __unused,
6734 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006735{
6736 return -ENOSYS;
6737}
6738
6739static size_t in_get_buffer_size(const struct audio_stream *stream)
6740{
6741 struct stream_in *in = (struct stream_in *)stream;
6742
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006743 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6744 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006745 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6746 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306747 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306748 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006749
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006750 return in->config.period_size * in->af_period_multiplier *
6751 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006752}
6753
6754static uint32_t in_get_channels(const struct audio_stream *stream)
6755{
6756 struct stream_in *in = (struct stream_in *)stream;
6757
6758 return in->channel_mask;
6759}
6760
6761static audio_format_t in_get_format(const struct audio_stream *stream)
6762{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006763 struct stream_in *in = (struct stream_in *)stream;
6764
6765 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006766}
6767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006768static int in_set_format(struct audio_stream *stream __unused,
6769 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770{
6771 return -ENOSYS;
6772}
6773
6774static int in_standby(struct audio_stream *stream)
6775{
6776 struct stream_in *in = (struct stream_in *)stream;
6777 struct audio_device *adev = in->dev;
6778 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306779 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6780 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006781 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306782
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006783 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006784 if (!in->standby && in->is_st_session) {
6785 ALOGD("%s: sound trigger pcm stop lab", __func__);
6786 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006787 if (adev->num_va_sessions > 0)
6788 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006789 in->standby = 1;
6790 }
6791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006792 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006793 if (adev->adm_deregister_stream)
6794 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6795
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006796 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006797 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006798 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006799 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006800 voice_extn_compress_voip_close_input_stream(stream);
6801 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006802 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6803 do_stop = in->capture_started;
6804 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006805 if (in->mmap_shared_memory_fd >= 0) {
6806 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6807 __func__, in->mmap_shared_memory_fd);
6808 close(in->mmap_shared_memory_fd);
6809 in->mmap_shared_memory_fd = -1;
6810 }
Zhou Songa8895042016-07-05 17:54:22 +08006811 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306812 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306813 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006814 }
6815
Arun Mirpuri5d170872019-03-26 13:21:31 -07006816 if (in->pcm) {
6817 ATRACE_BEGIN("pcm_in_close");
6818 pcm_close(in->pcm);
6819 ATRACE_END();
6820 in->pcm = NULL;
6821 }
6822
Carter Hsu2e429db2019-05-14 18:50:52 +08006823 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006824 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006825
George Gao3018ede2019-10-23 13:23:00 -07006826 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6827 if (adev->num_va_sessions > 0)
6828 adev->num_va_sessions--;
6829 }
Quinn Malef6050362019-01-30 15:55:40 -08006830
Eric Laurent150dbfe2013-02-27 14:31:02 -08006831 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006832 }
6833 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006834 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835 return status;
6836}
6837
Aalique Grahame22e49102018-12-18 14:23:57 -08006838static int in_dump(const struct audio_stream *stream,
6839 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840{
Aalique Grahame22e49102018-12-18 14:23:57 -08006841 struct stream_in *in = (struct stream_in *)stream;
6842
6843 // We try to get the lock for consistency,
6844 // but it isn't necessary for these variables.
6845 // If we're not in standby, we may be blocked on a read.
6846 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6847 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6848 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6849 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6850
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006851 char buffer[256]; // for statistics formatting
6852 if (in->start_latency_ms.n > 0) {
6853 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6854 dprintf(fd, " Start latency ms: %s\n", buffer);
6855 }
6856
Aalique Grahame22e49102018-12-18 14:23:57 -08006857 if (locked) {
6858 pthread_mutex_unlock(&in->lock);
6859 }
6860
6861 // dump error info
6862 (void)error_log_dump(
6863 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006865 return 0;
6866}
6867
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306868static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6869{
6870 if (!stream || !parms)
6871 return;
6872
6873 struct stream_in *in = (struct stream_in *)stream;
6874 struct audio_device *adev = in->dev;
6875
6876 card_status_t status;
6877 int card;
6878 if (parse_snd_card_status(parms, &card, &status) < 0)
6879 return;
6880
6881 pthread_mutex_lock(&adev->lock);
6882 bool valid_cb = (card == adev->snd_card);
6883 pthread_mutex_unlock(&adev->lock);
6884
6885 if (!valid_cb)
6886 return;
6887
6888 lock_input_stream(in);
6889 if (in->card_status != status)
6890 in->card_status = status;
6891 pthread_mutex_unlock(&in->lock);
6892
6893 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6894 use_case_table[in->usecase],
6895 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6896
6897 // a better solution would be to report error back to AF and let
6898 // it put the stream to standby
6899 if (status == CARD_STATUS_OFFLINE)
6900 in_standby(&in->stream.common);
6901
6902 return;
6903}
6904
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006905int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006906 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006907 audio_source_t source)
6908{
6909 struct audio_device *adev = in->dev;
6910 int ret = 0;
6911
6912 lock_input_stream(in);
6913 pthread_mutex_lock(&adev->lock);
6914
6915 /* no audio source uses val == 0 */
6916 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6917 in->source = source;
6918 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6919 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6920 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6921 (in->config.rate == 8000 || in->config.rate == 16000 ||
6922 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6923 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6924 ret = voice_extn_compress_voip_open_input_stream(in);
6925 if (ret != 0) {
6926 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6927 __func__, ret);
6928 }
6929 }
6930 }
6931
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006932 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6933 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006934 // Workaround: If routing to an non existing usb device, fail gracefully
6935 // The routing request will otherwise block during 10 second
6936 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006937 struct str_parms *usb_addr =
6938 str_parms_create_str(get_usb_device_address(devices));
6939 if (is_usb_in_device_type(devices) && usb_addr &&
6940 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006941 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6942 ret = -ENOSYS;
6943 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006944 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006945 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006946 if (!in->standby && !in->is_st_session) {
6947 ALOGV("update input routing change");
6948 // inform adm before actual routing to prevent glitches.
6949 if (adev->adm_on_routing_change) {
6950 adev->adm_on_routing_change(adev->adm_data,
6951 in->capture_handle);
6952 ret = select_devices(adev, in->usecase);
6953 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6954 adev->adm_routing_changed = true;
6955 }
6956 }
6957 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006958 if (usb_addr)
6959 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006960 }
6961 pthread_mutex_unlock(&adev->lock);
6962 pthread_mutex_unlock(&in->lock);
6963
6964 ALOGD("%s: exit: status(%d)", __func__, ret);
6965 return ret;
6966}
6967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006968static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6969{
6970 struct stream_in *in = (struct stream_in *)stream;
6971 struct audio_device *adev = in->dev;
6972 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306974 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006975
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306976 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006977 parms = str_parms_create_str(kvpairs);
6978
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306979 if (!parms)
6980 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006981 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006982 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006983
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306984 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6985 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306986 strlcpy(in->profile, value, sizeof(in->profile));
6987 ALOGV("updating stream profile with value '%s'", in->profile);
6988 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6989 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006990 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306991 in->sample_rate, in->bit_width,
6992 in->profile, &in->app_type_cfg);
6993 }
6994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006995 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006996 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006997
6998 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306999error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307000 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007001}
7002
7003static char* in_get_parameters(const struct audio_stream *stream,
7004 const char *keys)
7005{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007006 struct stream_in *in = (struct stream_in *)stream;
7007 struct str_parms *query = str_parms_create_str(keys);
7008 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007009 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007010
7011 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007012 if (reply) {
7013 str_parms_destroy(reply);
7014 }
7015 if (query) {
7016 str_parms_destroy(query);
7017 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007018 ALOGE("in_get_parameters: failed to create query or reply");
7019 return NULL;
7020 }
7021
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007022 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007023
7024 voice_extn_in_get_parameters(in, query, reply);
7025
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007026 stream_get_parameter_channels(query, reply,
7027 &in->supported_channel_masks[0]);
7028 stream_get_parameter_formats(query, reply,
7029 &in->supported_formats[0]);
7030 stream_get_parameter_rates(query, reply,
7031 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007032 str = str_parms_to_str(reply);
7033 str_parms_destroy(query);
7034 str_parms_destroy(reply);
7035
7036 ALOGV("%s: exit: returns - %s", __func__, str);
7037 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007038}
7039
Aalique Grahame22e49102018-12-18 14:23:57 -08007040static int in_set_gain(struct audio_stream_in *stream,
7041 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007042{
Aalique Grahame22e49102018-12-18 14:23:57 -08007043 struct stream_in *in = (struct stream_in *)stream;
7044 char mixer_ctl_name[128];
7045 struct mixer_ctl *ctl;
7046 int ctl_value;
7047
7048 ALOGV("%s: gain %f", __func__, gain);
7049
7050 if (stream == NULL)
7051 return -EINVAL;
7052
7053 /* in_set_gain() only used to silence MMAP capture for now */
7054 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7055 return -ENOSYS;
7056
7057 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7058
7059 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7060 if (!ctl) {
7061 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7062 __func__, mixer_ctl_name);
7063 return -ENOSYS;
7064 }
7065
7066 if (gain < RECORD_GAIN_MIN)
7067 gain = RECORD_GAIN_MIN;
7068 else if (gain > RECORD_GAIN_MAX)
7069 gain = RECORD_GAIN_MAX;
7070 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7071
7072 mixer_ctl_set_value(ctl, 0, ctl_value);
7073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007074 return 0;
7075}
7076
7077static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7078 size_t bytes)
7079{
7080 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307081
7082 if (in == NULL) {
7083 ALOGE("%s: stream_in ptr is NULL", __func__);
7084 return -EINVAL;
7085 }
7086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007087 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307088 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307089 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007090
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007091 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307092
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007093 if (in->is_st_session) {
7094 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7095 /* Read from sound trigger HAL */
7096 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007097 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007098 if (adev->num_va_sessions < UINT_MAX)
7099 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007100 in->standby = 0;
7101 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007102 pthread_mutex_unlock(&in->lock);
7103 return bytes;
7104 }
7105
Haynes Mathew George16081042017-05-31 17:16:49 -07007106 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7107 ret = -ENOSYS;
7108 goto exit;
7109 }
7110
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007111 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7112 !in->standby && adev->adm_routing_changed) {
7113 ret = -ENOSYS;
7114 goto exit;
7115 }
7116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007117 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007118 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7119
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007120 pthread_mutex_lock(&adev->lock);
7121 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7122 ret = voice_extn_compress_voip_start_input_stream(in);
7123 else
7124 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007125 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7126 if (adev->num_va_sessions < UINT_MAX)
7127 adev->num_va_sessions++;
7128 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007129 pthread_mutex_unlock(&adev->lock);
7130 if (ret != 0) {
7131 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007132 }
7133 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007134
7135 // log startup time in ms.
7136 simple_stats_log(
7137 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307140 /* Avoid read if capture_stopped is set */
7141 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7142 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7143 ret = -EINVAL;
7144 goto exit;
7145 }
7146
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007147 // what's the duration requested by the client?
7148 long ns = 0;
7149
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307150 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007151 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7152 in->config.rate;
7153
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007154 ret = request_in_focus(in, ns);
7155 if (ret != 0)
7156 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007157 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007158
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307159 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307160 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7161 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307162 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007163 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307164 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007165 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007166 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007167 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007168 } else if (audio_extn_ffv_get_stream() == in) {
7169 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307170 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007171 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307172 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7173 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7174 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7175 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307176 ret = -EINVAL;
7177 goto exit;
7178 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307179 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307180 ret = -errno;
7181 }
7182 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307183 /* bytes read is always set to bytes for non compress usecases */
7184 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007185 }
7186
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007187 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007189 /*
Quinn Malef6050362019-01-30 15:55:40 -08007190 * Instead of writing zeroes here, we could trust the hardware to always
7191 * provide zeroes when muted. This is also muted with voice recognition
7192 * usecases so that other clients do not have access to voice recognition
7193 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007194 */
Quinn Malef6050362019-01-30 15:55:40 -08007195 if ((ret == 0 && voice_get_mic_mute(adev) &&
7196 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007197 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7198 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007199 (adev->num_va_sessions &&
7200 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7201 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7202 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007203 memset(buffer, 0, bytes);
7204
7205exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307206 frame_size = audio_stream_in_frame_size(stream);
7207 if (frame_size > 0)
7208 in->frames_read += bytes_read/frame_size;
7209
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007210 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307211 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007212 pthread_mutex_unlock(&in->lock);
7213
7214 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307215 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307216 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307217 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307218 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307219 in->standby = true;
7220 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307221 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307222 bytes_read = bytes;
7223 memset(buffer, 0, bytes);
7224 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007225 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007226 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7227 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007228 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307229 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307230 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007231 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307232 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007233}
7234
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007235static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236{
7237 return 0;
7238}
7239
Aalique Grahame22e49102018-12-18 14:23:57 -08007240static int in_get_capture_position(const struct audio_stream_in *stream,
7241 int64_t *frames, int64_t *time)
7242{
7243 if (stream == NULL || frames == NULL || time == NULL) {
7244 return -EINVAL;
7245 }
7246 struct stream_in *in = (struct stream_in *)stream;
7247 int ret = -ENOSYS;
7248
7249 lock_input_stream(in);
7250 // note: ST sessions do not close the alsa pcm driver synchronously
7251 // on standby. Therefore, we may return an error even though the
7252 // pcm stream is still opened.
7253 if (in->standby) {
7254 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7255 "%s stream in standby but pcm not NULL for non ST session", __func__);
7256 goto exit;
7257 }
7258 if (in->pcm) {
7259 struct timespec timestamp;
7260 unsigned int avail;
7261 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7262 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007263 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
George Gao9ba8a142020-07-23 14:30:03 -07007264 - platform_capture_latency(in) * 1000LL;
Aalique Grahame22e49102018-12-18 14:23:57 -08007265 ret = 0;
7266 }
7267 }
7268exit:
7269 pthread_mutex_unlock(&in->lock);
7270 return ret;
7271}
7272
Carter Hsu2e429db2019-05-14 18:50:52 +08007273static int in_update_effect_list(bool add, effect_handle_t effect,
7274 struct listnode *head)
7275{
7276 struct listnode *node;
7277 struct in_effect_list *elist = NULL;
7278 struct in_effect_list *target = NULL;
7279 int ret = 0;
7280
7281 if (!head)
7282 return ret;
7283
7284 list_for_each(node, head) {
7285 elist = node_to_item(node, struct in_effect_list, list);
7286 if (elist->handle == effect) {
7287 target = elist;
7288 break;
7289 }
7290 }
7291
7292 if (add) {
7293 if (target) {
7294 ALOGD("effect %p already exist", effect);
7295 return ret;
7296 }
7297
7298 target = (struct in_effect_list *)
7299 calloc(1, sizeof(struct in_effect_list));
7300
7301 if (!target) {
7302 ALOGE("%s:fail to allocate memory", __func__);
7303 return -ENOMEM;
7304 }
7305
7306 target->handle = effect;
7307 list_add_tail(head, &target->list);
7308 } else {
7309 if (target) {
7310 list_remove(&target->list);
7311 free(target);
7312 }
7313 }
7314
7315 return ret;
7316}
7317
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007318static int add_remove_audio_effect(const struct audio_stream *stream,
7319 effect_handle_t effect,
7320 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007321{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007322 struct stream_in *in = (struct stream_in *)stream;
7323 int status = 0;
7324 effect_descriptor_t desc;
7325
7326 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007327 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7328
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007329 if (status != 0)
7330 return status;
7331
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007332 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007333 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007334 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007335 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7336 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007337 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007338
7339 in_update_effect_list(enable, effect, &in->aec_list);
7340 enable = !list_empty(&in->aec_list);
7341 if (enable == in->enable_aec)
7342 goto exit;
7343
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007344 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007345 ALOGD("AEC enable %d", enable);
7346
Aalique Grahame22e49102018-12-18 14:23:57 -08007347 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7348 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7349 in->dev->enable_voicerx = enable;
7350 struct audio_usecase *usecase;
7351 struct listnode *node;
7352 list_for_each(node, &in->dev->usecase_list) {
7353 usecase = node_to_item(node, struct audio_usecase, list);
7354 if (usecase->type == PCM_PLAYBACK)
7355 select_devices(in->dev, usecase->id);
7356 }
7357 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007358 if (!in->standby) {
7359 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7360 select_devices(in->dev, in->usecase);
7361 }
7362
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007363 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007364 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7365
7366 in_update_effect_list(enable, effect, &in->ns_list);
7367 enable = !list_empty(&in->ns_list);
7368 if (enable == in->enable_ns)
7369 goto exit;
7370
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007371 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007372 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007373 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007374 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7375 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007376 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7377 select_devices(in->dev, in->usecase);
7378 } else
7379 select_devices(in->dev, in->usecase);
7380 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007381 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007382exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007383 pthread_mutex_unlock(&in->dev->lock);
7384 pthread_mutex_unlock(&in->lock);
7385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007386 return 0;
7387}
7388
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007389static int in_add_audio_effect(const struct audio_stream *stream,
7390 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007391{
Eric Laurent994a6932013-07-17 11:51:42 -07007392 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007393 return add_remove_audio_effect(stream, effect, true);
7394}
7395
7396static int in_remove_audio_effect(const struct audio_stream *stream,
7397 effect_handle_t effect)
7398{
Eric Laurent994a6932013-07-17 11:51:42 -07007399 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007400 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007401}
7402
Derek Chenf939fb72018-11-13 13:34:41 -08007403streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7404 audio_io_handle_t input)
7405{
7406 struct listnode *node;
7407
7408 list_for_each(node, &dev->active_inputs_list) {
7409 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7410 streams_input_ctxt_t,
7411 list);
7412 if (in_ctxt->input->capture_handle == input) {
7413 return in_ctxt;
7414 }
7415 }
7416 return NULL;
7417}
7418
7419streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7420 audio_io_handle_t output)
7421{
7422 struct listnode *node;
7423
7424 list_for_each(node, &dev->active_outputs_list) {
7425 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7426 streams_output_ctxt_t,
7427 list);
7428 if (out_ctxt->output->handle == output) {
7429 return out_ctxt;
7430 }
7431 }
7432 return NULL;
7433}
7434
Haynes Mathew George16081042017-05-31 17:16:49 -07007435static int in_stop(const struct audio_stream_in* stream)
7436{
7437 struct stream_in *in = (struct stream_in *)stream;
7438 struct audio_device *adev = in->dev;
7439
7440 int ret = -ENOSYS;
7441 ALOGV("%s", __func__);
7442 pthread_mutex_lock(&adev->lock);
7443 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7444 in->capture_started && in->pcm != NULL) {
7445 pcm_stop(in->pcm);
7446 ret = stop_input_stream(in);
7447 in->capture_started = false;
7448 }
7449 pthread_mutex_unlock(&adev->lock);
7450 return ret;
7451}
7452
7453static int in_start(const struct audio_stream_in* stream)
7454{
7455 struct stream_in *in = (struct stream_in *)stream;
7456 struct audio_device *adev = in->dev;
7457 int ret = -ENOSYS;
7458
7459 ALOGV("%s in %p", __func__, in);
7460 pthread_mutex_lock(&adev->lock);
7461 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7462 !in->capture_started && in->pcm != NULL) {
7463 if (!in->capture_started) {
7464 ret = start_input_stream(in);
7465 if (ret == 0) {
7466 in->capture_started = true;
7467 }
7468 }
7469 }
7470 pthread_mutex_unlock(&adev->lock);
7471 return ret;
7472}
7473
Phil Burke0a86d12019-02-16 22:28:11 -08007474// Read offset for the positional timestamp from a persistent vendor property.
7475// This is to workaround apparent inaccuracies in the timing information that
7476// is used by the AAudio timing model. The inaccuracies can cause glitches.
7477static int64_t in_get_mmap_time_offset() {
7478 const int32_t kDefaultOffsetMicros = 0;
7479 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007480 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007481 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7482 return mmap_time_offset_micros * (int64_t)1000;
7483}
7484
Haynes Mathew George16081042017-05-31 17:16:49 -07007485static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7486 int32_t min_size_frames,
7487 struct audio_mmap_buffer_info *info)
7488{
7489 struct stream_in *in = (struct stream_in *)stream;
7490 struct audio_device *adev = in->dev;
7491 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007492 unsigned int offset1 = 0;
7493 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007494 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007495 uint32_t mmap_size = 0;
7496 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007497
7498 pthread_mutex_lock(&adev->lock);
7499 ALOGV("%s in %p", __func__, in);
7500
Sharad Sanglec6f32552018-05-04 16:15:38 +05307501 if (CARD_STATUS_OFFLINE == in->card_status||
7502 CARD_STATUS_OFFLINE == adev->card_status) {
7503 ALOGW("in->card_status or adev->card_status offline, try again");
7504 ret = -EIO;
7505 goto exit;
7506 }
7507
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307508 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007509 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7510 ret = -EINVAL;
7511 goto exit;
7512 }
7513 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7514 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7515 ALOGV("%s in %p", __func__, in);
7516 ret = -ENOSYS;
7517 goto exit;
7518 }
7519 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7520 if (in->pcm_device_id < 0) {
7521 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7522 __func__, in->pcm_device_id, in->usecase);
7523 ret = -EINVAL;
7524 goto exit;
7525 }
7526
7527 adjust_mmap_period_count(&in->config, min_size_frames);
7528
7529 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7530 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7531 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7532 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307533 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307534 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7535 in->card_status = CARD_STATUS_OFFLINE;
7536 adev->card_status = CARD_STATUS_OFFLINE;
7537 ret = -EIO;
7538 goto exit;
7539 }
7540
Haynes Mathew George16081042017-05-31 17:16:49 -07007541 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7542 step = "open";
7543 ret = -ENODEV;
7544 goto exit;
7545 }
7546
7547 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7548 if (ret < 0) {
7549 step = "begin";
7550 goto exit;
7551 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007552
juyuchen626833d2019-06-04 16:48:02 +08007553 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007554 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7555 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7556 info->burst_size_frames = in->config.period_size;
7557 ret = platform_get_mmap_data_fd(adev->platform,
7558 in->pcm_device_id, 1 /*capture*/,
7559 &info->shared_memory_fd,
7560 &mmap_size);
7561 if (ret < 0) {
7562 // Fall back to non exclusive mode
7563 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7564 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007565 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7566 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7567
Arun Mirpuri5d170872019-03-26 13:21:31 -07007568 if (mmap_size < buffer_size) {
7569 step = "mmap";
7570 goto exit;
7571 }
juyuchen626833d2019-06-04 16:48:02 +08007572 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007573 }
7574
7575 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007576
7577 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7578 if (ret < 0) {
7579 step = "commit";
7580 goto exit;
7581 }
7582
Phil Burke0a86d12019-02-16 22:28:11 -08007583 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7584
Haynes Mathew George16081042017-05-31 17:16:49 -07007585 in->standby = false;
7586 ret = 0;
7587
7588 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7589 __func__, info->shared_memory_address, info->buffer_size_frames);
7590
7591exit:
7592 if (ret != 0) {
7593 if (in->pcm == NULL) {
7594 ALOGE("%s: %s - %d", __func__, step, ret);
7595 } else {
7596 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7597 pcm_close(in->pcm);
7598 in->pcm = NULL;
7599 }
7600 }
7601 pthread_mutex_unlock(&adev->lock);
7602 return ret;
7603}
7604
7605static int in_get_mmap_position(const struct audio_stream_in *stream,
7606 struct audio_mmap_position *position)
7607{
7608 struct stream_in *in = (struct stream_in *)stream;
7609 ALOGVV("%s", __func__);
7610 if (position == NULL) {
7611 return -EINVAL;
7612 }
7613 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7614 return -ENOSYS;
7615 }
7616 if (in->pcm == NULL) {
7617 return -ENOSYS;
7618 }
7619 struct timespec ts = { 0, 0 };
7620 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7621 if (ret < 0) {
7622 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7623 return ret;
7624 }
Phil Burke0a86d12019-02-16 22:28:11 -08007625 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7626 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007627 return 0;
7628}
7629
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307630static int in_get_active_microphones(const struct audio_stream_in *stream,
7631 struct audio_microphone_characteristic_t *mic_array,
7632 size_t *mic_count) {
7633 struct stream_in *in = (struct stream_in *)stream;
7634 struct audio_device *adev = in->dev;
7635 ALOGVV("%s", __func__);
7636
7637 lock_input_stream(in);
7638 pthread_mutex_lock(&adev->lock);
7639 int ret = platform_get_active_microphones(adev->platform,
7640 audio_channel_count_from_in_mask(in->channel_mask),
7641 in->usecase, mic_array, mic_count);
7642 pthread_mutex_unlock(&adev->lock);
7643 pthread_mutex_unlock(&in->lock);
7644
7645 return ret;
7646}
7647
7648static int adev_get_microphones(const struct audio_hw_device *dev,
7649 struct audio_microphone_characteristic_t *mic_array,
7650 size_t *mic_count) {
7651 struct audio_device *adev = (struct audio_device *)dev;
7652 ALOGVV("%s", __func__);
7653
7654 pthread_mutex_lock(&adev->lock);
7655 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7656 pthread_mutex_unlock(&adev->lock);
7657
7658 return ret;
7659}
juyuchendb308c22019-01-21 11:57:17 -07007660
7661static void in_update_sink_metadata(struct audio_stream_in *stream,
7662 const struct sink_metadata *sink_metadata) {
7663
7664 if (stream == NULL
7665 || sink_metadata == NULL
7666 || sink_metadata->tracks == NULL) {
7667 return;
7668 }
7669
7670 int error = 0;
7671 struct stream_in *in = (struct stream_in *)stream;
7672 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007673 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007674 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007675
7676 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007677
7678 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007679 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007680
7681 lock_input_stream(in);
7682 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007683 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007684
Zhou Song62ea0282020-03-22 19:53:01 +08007685 is_ha_usecase = adev->ha_proxy_enable ?
7686 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7687 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7688 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007689 && adev->voice_tx_output != NULL) {
7690 /* Use the rx device from afe-proxy record to route voice call because
7691 there is no routing if tx device is on primary hal and rx device
7692 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007693 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007694
7695 if (!voice_is_call_state_active(adev)) {
7696 if (adev->mode == AUDIO_MODE_IN_CALL) {
7697 adev->current_call_output = adev->voice_tx_output;
7698 error = voice_start_call(adev);
7699 if (error != 0)
7700 ALOGE("%s: start voice call failed %d", __func__, error);
7701 }
7702 } else {
7703 adev->current_call_output = adev->voice_tx_output;
7704 voice_update_devices_for_all_voice_usecases(adev);
7705 }
7706 }
7707
7708 pthread_mutex_unlock(&adev->lock);
7709 pthread_mutex_unlock(&in->lock);
7710}
7711
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307712int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007713 audio_io_handle_t handle,
7714 audio_devices_t devices,
7715 audio_output_flags_t flags,
7716 struct audio_config *config,
7717 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007718 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007719{
7720 struct audio_device *adev = (struct audio_device *)dev;
7721 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307722 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007723 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007724 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307725 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007726 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7727 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7728 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7729 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007730 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007731 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7732 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007733 bool force_haptic_path =
7734 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007735 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08007736#ifdef AUDIO_GKI_ENABLED
7737 __s32 *generic_dec;
7738#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007739
kunleizdff872d2018-08-20 14:40:33 +08007740 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007741 is_usb_dev = false;
7742 devices = AUDIO_DEVICE_OUT_SPEAKER;
7743 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7744 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007745 if (config->format == AUDIO_FORMAT_DEFAULT)
7746 config->format = AUDIO_FORMAT_PCM_16_BIT;
7747 if (config->sample_rate == 0)
7748 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7749 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7750 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007751 }
7752
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007753 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307754
Rahul Sharma99770982019-03-06 17:05:26 +05307755 pthread_mutex_lock(&adev->lock);
7756 if (out_get_stream(adev, handle) != NULL) {
7757 ALOGW("%s, output stream already opened", __func__);
7758 ret = -EEXIST;
7759 }
7760 pthread_mutex_unlock(&adev->lock);
7761 if (ret)
7762 return ret;
7763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007764 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7765
Mingming Yin3a941d42016-02-17 18:08:05 -08007766 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007767 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7768 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307769
7770
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007771 if (!out) {
7772 return -ENOMEM;
7773 }
7774
Haynes Mathew George204045b2015-02-25 20:32:03 -08007775 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007776 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08007777 pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007778 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007779 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007781 if (devices == AUDIO_DEVICE_NONE)
7782 devices = AUDIO_DEVICE_OUT_SPEAKER;
7783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007784 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007785 list_init(&out->device_list);
7786 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007787 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007788 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007789 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307790 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307791 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7792 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7793 else
7794 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007795 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007796 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007797 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307798 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307799 out->started = 0;
Zhou Song1f93fa52020-11-20 13:57:39 +08007800 out->a2dp_muted = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007801 out->hal_output_suspend_supported = 0;
7802 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307803 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307804 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307805 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007806 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007807
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307808 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307809 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007810 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7811
Aalique Grahame22e49102018-12-18 14:23:57 -08007812 if (direct_dev &&
7813 (audio_is_linear_pcm(out->format) ||
7814 config->format == AUDIO_FORMAT_DEFAULT) &&
7815 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7816 audio_format_t req_format = config->format;
7817 audio_channel_mask_t req_channel_mask = config->channel_mask;
7818 uint32_t req_sample_rate = config->sample_rate;
7819
7820 pthread_mutex_lock(&adev->lock);
7821 if (is_hdmi) {
7822 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7823 ret = read_hdmi_sink_caps(out);
7824 if (config->sample_rate == 0)
7825 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7826 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7827 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7828 if (config->format == AUDIO_FORMAT_DEFAULT)
7829 config->format = AUDIO_FORMAT_PCM_16_BIT;
7830 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007831 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7832 &config->format,
7833 &out->supported_formats[0],
7834 MAX_SUPPORTED_FORMATS,
7835 &config->channel_mask,
7836 &out->supported_channel_masks[0],
7837 MAX_SUPPORTED_CHANNEL_MASKS,
7838 &config->sample_rate,
7839 &out->supported_sample_rates[0],
7840 MAX_SUPPORTED_SAMPLE_RATES);
7841 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007842 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007843
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007844 pthread_mutex_unlock(&adev->lock);
7845 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007846 if (ret == -ENOSYS) {
7847 /* ignore and go with default */
7848 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007849 }
7850 // For MMAP NO IRQ, allow conversions in ADSP
7851 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7852 goto error_open;
7853 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007854 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007855 goto error_open;
7856 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007857
7858 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7859 config->sample_rate = req_sample_rate;
7860 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7861 config->channel_mask = req_channel_mask;
7862 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7863 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007864 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007865
7866 out->sample_rate = config->sample_rate;
7867 out->channel_mask = config->channel_mask;
7868 out->format = config->format;
7869 if (is_hdmi) {
7870 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7871 out->config = pcm_config_hdmi_multi;
7872 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7873 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7874 out->config = pcm_config_mmap_playback;
7875 out->stream.start = out_start;
7876 out->stream.stop = out_stop;
7877 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7878 out->stream.get_mmap_position = out_get_mmap_position;
7879 } else {
7880 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7881 out->config = pcm_config_hifi;
7882 }
7883
7884 out->config.rate = out->sample_rate;
7885 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7886 if (is_hdmi) {
7887 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7888 audio_bytes_per_sample(out->format));
7889 }
7890 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007891 }
7892
Derek Chenf6318be2017-06-12 17:16:24 -04007893 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007894 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007895 /* extract car audio stream index */
7896 out->car_audio_stream =
7897 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7898 if (out->car_audio_stream < 0) {
7899 ALOGE("%s: invalid car audio stream %x",
7900 __func__, out->car_audio_stream);
7901 ret = -EINVAL;
7902 goto error_open;
7903 }
Derek Chen5f67a942020-02-24 23:08:13 -08007904 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007905 }
7906
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007907 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007908 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007909 if (!voice_extn_is_compress_voip_supported()) {
7910 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7911 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007912 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307913 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007914 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7915 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007916 out->volume_l = INVALID_OUT_VOLUME;
7917 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007918
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007919 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007920 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007921 uint32_t channel_count =
7922 audio_channel_count_from_out_mask(out->channel_mask);
Ramjee Singh8e34a2f2020-08-06 16:30:48 +05307923 out->config.channels = channel_count;
7924
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007925 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7926 out->sample_rate, out->format,
7927 channel_count, false);
7928 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7929 if (frame_size != 0)
7930 out->config.period_size = buffer_size / frame_size;
7931 else
7932 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007933 }
7934 } else {
7935 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7936 voice_extn_compress_voip_is_active(out->dev)) &&
7937 (voice_extn_compress_voip_is_config_supported(config))) {
7938 ret = voice_extn_compress_voip_open_output_stream(out);
7939 if (ret != 0) {
7940 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7941 __func__, ret);
7942 goto error_open;
7943 }
Sujin Panicker19027262019-09-16 18:28:06 +05307944 } else {
7945 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7946 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007947 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007948 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007949 } else if (audio_is_linear_pcm(out->format) &&
7950 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7951 out->channel_mask = config->channel_mask;
7952 out->sample_rate = config->sample_rate;
7953 out->format = config->format;
7954 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7955 // does this change?
7956 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7957 out->config.rate = config->sample_rate;
7958 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7959 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7960 audio_bytes_per_sample(config->format));
7961 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007962 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307963 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307964 pthread_mutex_lock(&adev->lock);
7965 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7966 pthread_mutex_unlock(&adev->lock);
7967
7968 // reject offload during card offline to allow
7969 // fallback to s/w paths
7970 if (offline) {
7971 ret = -ENODEV;
7972 goto error_open;
7973 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007975 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7976 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7977 ALOGE("%s: Unsupported Offload information", __func__);
7978 ret = -EINVAL;
7979 goto error_open;
7980 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007981
Atul Khare3fa6e542017-08-09 00:56:17 +05307982 if (config->offload_info.format == 0)
7983 config->offload_info.format = config->format;
7984 if (config->offload_info.sample_rate == 0)
7985 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007986
Mingming Yin90310102013-11-13 16:57:00 -08007987 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307988 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007989 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007990 ret = -EINVAL;
7991 goto error_open;
7992 }
7993
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007994 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7995 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7996 (audio_extn_passthru_is_passthrough_stream(out)) &&
7997 !((config->sample_rate == 48000) ||
7998 (config->sample_rate == 96000) ||
7999 (config->sample_rate == 192000))) {
8000 ALOGE("%s: Unsupported sample rate %d for audio format %x",
8001 __func__, config->sample_rate, config->offload_info.format);
8002 ret = -EINVAL;
8003 goto error_open;
8004 }
8005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008006 out->compr_config.codec = (struct snd_codec *)
8007 calloc(1, sizeof(struct snd_codec));
8008
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008009 if (!out->compr_config.codec) {
8010 ret = -ENOMEM;
8011 goto error_open;
8012 }
8013
Dhananjay Kumarac341582017-02-23 23:42:25 +05308014 out->stream.pause = out_pause;
8015 out->stream.resume = out_resume;
8016 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05308017 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308018 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07008019 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05308020 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07008021 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05308022 } else {
8023 out->usecase = get_offload_usecase(adev, false /* is_compress */);
8024 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07008025 }
vivek mehta446c3962015-09-14 10:57:35 -07008026
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308027 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8028 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08008029#ifdef AUDIO_GKI_ENABLED
8030 /* out->compr_config.codec->reserved[1] is for flags */
8031 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
8032#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308033 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08008034#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308035 }
8036
vivek mehta446c3962015-09-14 10:57:35 -07008037 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008038 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08008039 config->format == 0 && config->sample_rate == 0 &&
8040 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07008041 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08008042 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
8043 } else {
8044 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
8045 ret = -EEXIST;
8046 goto error_open;
8047 }
vivek mehta446c3962015-09-14 10:57:35 -07008048 }
8049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008050 if (config->offload_info.channel_mask)
8051 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008052 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008053 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008054 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008055 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05308056 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008057 ret = -EINVAL;
8058 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008059 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008060
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008061 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008062 out->sample_rate = config->offload_info.sample_rate;
8063
Mingming Yin3ee55c62014-08-04 14:23:35 -07008064 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008065
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308066 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308067 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308068 audio_extn_dolby_send_ddp_endp_params(adev);
8069 audio_extn_dolby_set_dmid(adev);
8070 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008071
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008072 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008073 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008074 out->compr_config.codec->bit_rate =
8075 config->offload_info.bit_rate;
8076 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308077 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008078 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308079 /* Update bit width only for non passthrough usecases.
8080 * For passthrough usecases, the output will always be opened @16 bit
8081 */
8082 if (!audio_extn_passthru_is_passthrough_stream(out))
8083 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308084
8085 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008086#ifdef AUDIO_GKI_ENABLED
8087 /* out->compr_config.codec->reserved[1] is for flags */
8088 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8089 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8090#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308091 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8092 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008093#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308094
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008095 /*TODO: Do we need to change it for passthrough */
8096 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008097
Manish Dewangana6fc5442015-08-24 20:30:31 +05308098 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8099 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308100 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308101 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308102 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8103 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308104
8105 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8106 AUDIO_FORMAT_PCM) {
8107
8108 /*Based on platform support, configure appropriate alsa format for corresponding
8109 *hal input format.
8110 */
8111 out->compr_config.codec->format = hal_format_to_alsa(
8112 config->offload_info.format);
8113
Ashish Jain83a6cc22016-06-28 14:34:17 +05308114 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308115 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308116 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308117
Dhananjay Kumarac341582017-02-23 23:42:25 +05308118 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308119 *hal input format and alsa format might differ based on platform support.
8120 */
8121 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308122 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308123
8124 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8125
Deeraj Soman93155a62019-09-30 19:00:37 +05308126 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8127 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8128 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8129 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8130 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308131
Ashish Jainf1eaa582016-05-23 20:54:24 +05308132 /* Check if alsa session is configured with the same format as HAL input format,
8133 * if not then derive correct fragment size needed to accomodate the
8134 * conversion of HAL input format to alsa format.
8135 */
8136 audio_extn_utils_update_direct_pcm_fragment_size(out);
8137
8138 /*if hal input and output fragment size is different this indicates HAL input format is
8139 *not same as the alsa format
8140 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308141 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308142 /*Allocate a buffer to convert input data to the alsa configured format.
8143 *size of convert buffer is equal to the size required to hold one fragment size
8144 *worth of pcm data, this is because flinger does not write more than fragment_size
8145 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308146 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8147 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308148 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8149 ret = -ENOMEM;
8150 goto error_open;
8151 }
8152 }
8153 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8154 out->compr_config.fragment_size =
8155 audio_extn_passthru_get_buffer_size(&config->offload_info);
8156 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8157 } else {
8158 out->compr_config.fragment_size =
8159 platform_get_compress_offload_buffer_size(&config->offload_info);
8160 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8161 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008162
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308163 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8164 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8165 }
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008166 if (config->offload_info.format == AUDIO_FORMAT_FLAC) {
8167#ifdef AUDIO_GKI_ENABLED
8168 generic_dec =
8169 &(out->compr_config.codec->options.generic.reserved[1]);
8170 ((struct snd_generic_dec_flac *)generic_dec)->sample_size =
8171 AUDIO_OUTPUT_BIT_WIDTH;
8172#else
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308173 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Xiaojun Sang782e5b12020-06-29 21:13:06 +08008174#endif
8175 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008176
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308177 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8178 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8179 }
8180
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008181 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8182 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008183
Manish Dewangan69426c82017-01-30 17:35:36 +05308184 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8185 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8186 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8187 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8188 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8189 } else {
8190 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8191 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008192
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308193 memset(&out->channel_map_param, 0,
8194 sizeof(struct audio_out_channel_map_param));
8195
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008196 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308197 out->send_next_track_params = false;
8198 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008199 out->offload_state = OFFLOAD_STATE_IDLE;
8200 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008201 out->writeAt.tv_sec = 0;
8202 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008203
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008204 audio_extn_dts_create_state_notifier_node(out->usecase);
8205
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008206 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8207 __func__, config->offload_info.version,
8208 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308209
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308210 /* Check if DSD audio format is supported in codec
8211 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308212 */
8213
8214 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308215 (!platform_check_codec_dsd_support(adev->platform) ||
8216 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308217 ret = -EINVAL;
8218 goto error_open;
8219 }
8220
Ashish Jain5106d362016-05-11 19:23:33 +05308221 /* Disable gapless if any of the following is true
8222 * passthrough playback
8223 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308224 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308225 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308226 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308227 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008228 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308229 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308230 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308231 check_and_set_gapless_mode(adev, false);
8232 } else
8233 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008234
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308235 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008236 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8237 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308238 if (config->format == AUDIO_FORMAT_DSD) {
8239 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008240#ifdef AUDIO_GKI_ENABLED
8241 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8242 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8243#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308244 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008245#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308246 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008247
8248 create_offload_callback_thread(out);
8249
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008250 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008251 switch (config->sample_rate) {
8252 case 0:
8253 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8254 break;
8255 case 8000:
8256 case 16000:
8257 case 48000:
8258 out->sample_rate = config->sample_rate;
8259 break;
8260 default:
8261 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8262 config->sample_rate);
8263 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8264 ret = -EINVAL;
8265 goto error_open;
8266 }
8267 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8268 switch (config->channel_mask) {
8269 case AUDIO_CHANNEL_NONE:
8270 case AUDIO_CHANNEL_OUT_STEREO:
8271 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8272 break;
8273 default:
8274 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8275 config->channel_mask);
8276 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8277 ret = -EINVAL;
8278 goto error_open;
8279 }
8280 switch (config->format) {
8281 case AUDIO_FORMAT_DEFAULT:
8282 case AUDIO_FORMAT_PCM_16_BIT:
8283 out->format = AUDIO_FORMAT_PCM_16_BIT;
8284 break;
8285 default:
8286 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8287 config->format);
8288 config->format = AUDIO_FORMAT_PCM_16_BIT;
8289 ret = -EINVAL;
8290 goto error_open;
8291 }
8292
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308293 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008294 if (ret != 0) {
8295 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008296 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008297 goto error_open;
8298 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008299 } else if (is_single_device_type_equal(&out->device_list,
8300 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008301 switch (config->sample_rate) {
8302 case 0:
8303 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8304 break;
8305 case 8000:
8306 case 16000:
8307 case 48000:
8308 out->sample_rate = config->sample_rate;
8309 break;
8310 default:
8311 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8312 config->sample_rate);
8313 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8314 ret = -EINVAL;
8315 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008316 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008317 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8318 switch (config->channel_mask) {
8319 case AUDIO_CHANNEL_NONE:
8320 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8321 break;
8322 case AUDIO_CHANNEL_OUT_STEREO:
8323 out->channel_mask = config->channel_mask;
8324 break;
8325 default:
8326 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8327 config->channel_mask);
8328 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8329 ret = -EINVAL;
8330 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008331 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008332 switch (config->format) {
8333 case AUDIO_FORMAT_DEFAULT:
8334 out->format = AUDIO_FORMAT_PCM_16_BIT;
8335 break;
8336 case AUDIO_FORMAT_PCM_16_BIT:
8337 out->format = config->format;
8338 break;
8339 default:
8340 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8341 config->format);
8342 config->format = AUDIO_FORMAT_PCM_16_BIT;
8343 ret = -EINVAL;
8344 break;
8345 }
8346 if (ret != 0)
8347 goto error_open;
8348
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008349 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8350 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008351 out->config.rate = out->sample_rate;
8352 out->config.channels =
8353 audio_channel_count_from_out_mask(out->channel_mask);
8354 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008355 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008356 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308357 unsigned int channels = 0;
8358 /*Update config params to default if not set by the caller*/
8359 if (config->sample_rate == 0)
8360 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8361 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8362 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8363 if (config->format == AUDIO_FORMAT_DEFAULT)
8364 config->format = AUDIO_FORMAT_PCM_16_BIT;
8365
8366 channels = audio_channel_count_from_out_mask(out->channel_mask);
8367
Varun Balaraje49253e2017-07-06 19:48:56 +05308368 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8369 out->usecase = get_interactive_usecase(adev);
8370 out->config = pcm_config_low_latency;
8371 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308372 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008373 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8374 out->flags);
8375 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008376 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8377 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8378 out->config = pcm_config_mmap_playback;
8379 out->stream.start = out_start;
8380 out->stream.stop = out_stop;
8381 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8382 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308383 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8384 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008385 out->hal_output_suspend_supported =
8386 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8387 out->dynamic_pm_qos_config_supported =
8388 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8389 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008390 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8391 } else {
8392 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8393 //the mixer path will be a string similar to "low-latency-playback resume"
8394 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8395 strlcat(out->pm_qos_mixer_path,
8396 " resume", MAX_MIXER_PATH_LEN);
8397 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8398 out->pm_qos_mixer_path);
8399 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308400 out->config = pcm_config_low_latency;
8401 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8402 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8403 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308404 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8405 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8406 if (out->config.period_size <= 0) {
8407 ALOGE("Invalid configuration period size is not valid");
8408 ret = -EINVAL;
8409 goto error_open;
8410 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008411 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8412 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8413 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008414 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8415 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8416 out->config = pcm_config_haptics_audio;
8417 if (force_haptic_path)
8418 adev->haptics_config = pcm_config_haptics_audio;
8419 else
8420 adev->haptics_config = pcm_config_haptics;
8421
Meng Wangd08ce322020-04-02 08:59:20 +08008422 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008423 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8424
8425 if (force_haptic_path) {
8426 out->config.channels = 1;
8427 adev->haptics_config.channels = 1;
8428 } else
8429 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 -08008430 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008431 ret = audio_extn_auto_hal_open_output_stream(out);
8432 if (ret) {
8433 ALOGE("%s: Failed to open output stream for bus device", __func__);
8434 ret = -EINVAL;
8435 goto error_open;
8436 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308437 } else {
8438 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008439 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8440 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308441 }
8442 out->hal_ip_format = format = out->format;
8443 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8444 out->hal_op_format = pcm_format_to_hal(out->config.format);
8445 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8446 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008447 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308448 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308449 if (out->hal_ip_format != out->hal_op_format) {
8450 uint32_t buffer_size = out->config.period_size *
8451 format_to_bitwidth_table[out->hal_op_format] *
8452 out->config.channels;
8453 out->convert_buffer = calloc(1, buffer_size);
8454 if (out->convert_buffer == NULL){
8455 ALOGE("Allocation failed for convert buffer for size %d",
8456 out->compr_config.fragment_size);
8457 ret = -ENOMEM;
8458 goto error_open;
8459 }
8460 ALOGD("Convert buffer allocated of size %d", buffer_size);
8461 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008462 }
8463
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008464 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8465 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308466
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008467 /* TODO remove this hardcoding and check why width is zero*/
8468 if (out->bit_width == 0)
8469 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308470 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008471 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008472 &out->device_list, out->flags,
8473 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308474 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308475 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008476 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008477 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8478 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008479 if(adev->primary_output == NULL)
8480 adev->primary_output = out;
8481 else {
8482 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008483 ret = -EEXIST;
8484 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008485 }
8486 }
8487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008488 /* Check if this usecase is already existing */
8489 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008490 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8491 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008492 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008494 ret = -EEXIST;
8495 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498 pthread_mutex_unlock(&adev->lock);
8499
8500 out->stream.common.get_sample_rate = out_get_sample_rate;
8501 out->stream.common.set_sample_rate = out_set_sample_rate;
8502 out->stream.common.get_buffer_size = out_get_buffer_size;
8503 out->stream.common.get_channels = out_get_channels;
8504 out->stream.common.get_format = out_get_format;
8505 out->stream.common.set_format = out_set_format;
8506 out->stream.common.standby = out_standby;
8507 out->stream.common.dump = out_dump;
8508 out->stream.common.set_parameters = out_set_parameters;
8509 out->stream.common.get_parameters = out_get_parameters;
8510 out->stream.common.add_audio_effect = out_add_audio_effect;
8511 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8512 out->stream.get_latency = out_get_latency;
8513 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008514#ifdef NO_AUDIO_OUT
8515 out->stream.write = out_write_for_no_output;
8516#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008517 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008518#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008519 out->stream.get_render_position = out_get_render_position;
8520 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008521 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008522
Haynes Mathew George16081042017-05-31 17:16:49 -07008523 if (out->realtime)
8524 out->af_period_multiplier = af_period_multiplier;
8525 else
8526 out->af_period_multiplier = 1;
8527
Andy Hunga1f48fa2019-07-01 18:14:53 -07008528 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008530 out->standby = 1;
Zhou Song1f93fa52020-11-20 13:57:39 +08008531 out->volume_l = PLAYBACK_GAIN_MAX;
8532 out->volume_r = PLAYBACK_GAIN_MAX;
Eric Laurenta9024de2013-04-04 09:19:12 -07008533 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008534 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008535
8536 config->format = out->stream.common.get_format(&out->stream.common);
8537 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8538 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308539 register_format(out->format, out->supported_formats);
8540 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8541 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008542
Aalique Grahame22e49102018-12-18 14:23:57 -08008543 out->error_log = error_log_create(
8544 ERROR_LOG_ENTRIES,
8545 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8546
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308547 /*
8548 By locking output stream before registering, we allow the callback
8549 to update stream's state only after stream's initial state is set to
8550 adev state.
8551 */
8552 lock_output_stream(out);
8553 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8554 pthread_mutex_lock(&adev->lock);
8555 out->card_status = adev->card_status;
8556 pthread_mutex_unlock(&adev->lock);
8557 pthread_mutex_unlock(&out->lock);
8558
Aalique Grahame22e49102018-12-18 14:23:57 -08008559 stream_app_type_cfg_init(&out->app_type_cfg);
8560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008561 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308562 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008563 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008564
8565 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8566 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8567 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008568 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308569 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008570 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008571 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308572 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8573 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008574 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8575 out->usecase, PCM_PLAYBACK);
8576 hdlr_stream_cfg.flags = out->flags;
8577 hdlr_stream_cfg.type = PCM_PLAYBACK;
8578 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8579 &hdlr_stream_cfg);
8580 if (ret) {
8581 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8582 out->adsp_hdlr_stream_handle = NULL;
8583 }
8584 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308585 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8586 is_direct_passthough, false);
8587 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8588 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008589 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008590 if (ret < 0) {
8591 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8592 out->ip_hdlr_handle = NULL;
8593 }
8594 }
Derek Chenf939fb72018-11-13 13:34:41 -08008595
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008596 ret = io_streams_map_insert(adev, &out->stream.common,
8597 out->handle, AUDIO_PATCH_HANDLE_NONE);
8598 if (ret != 0)
8599 goto error_open;
8600
Derek Chenf939fb72018-11-13 13:34:41 -08008601 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8602 calloc(1, sizeof(streams_output_ctxt_t));
8603 if (out_ctxt == NULL) {
8604 ALOGE("%s fail to allocate output ctxt", __func__);
8605 ret = -ENOMEM;
8606 goto error_open;
8607 }
8608 out_ctxt->output = out;
8609
8610 pthread_mutex_lock(&adev->lock);
8611 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8612 pthread_mutex_unlock(&adev->lock);
8613
Eric Laurent994a6932013-07-17 11:51:42 -07008614 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008615 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008616
8617error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308618 if (out->convert_buffer)
8619 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008620 free(out);
8621 *stream_out = NULL;
8622 ALOGD("%s: exit: ret %d", __func__, ret);
8623 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008624}
8625
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308626void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008627 struct audio_stream_out *stream)
8628{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008629 struct stream_out *out = (struct stream_out *)stream;
8630 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008631 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008632
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008633 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308634
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008635 io_streams_map_remove(adev, out->handle);
8636
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308637 // must deregister from sndmonitor first to prevent races
8638 // between the callback and close_stream
8639 audio_extn_snd_mon_unregister_listener(out);
8640
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008641 /* close adsp hdrl session before standby */
8642 if (out->adsp_hdlr_stream_handle) {
8643 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8644 if (ret)
8645 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8646 out->adsp_hdlr_stream_handle = NULL;
8647 }
8648
Manish Dewangan21a850a2017-08-14 12:03:55 +05308649 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008650 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8651 out->ip_hdlr_handle = NULL;
8652 }
8653
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008654 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308655 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008656 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308657 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308658 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008659 if(ret != 0)
8660 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8661 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008662 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008663 out_standby(&stream->common);
8664
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008665 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008666 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008667 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008668 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008669 if (out->compr_config.codec != NULL)
8670 free(out->compr_config.codec);
8671 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008672
Zhou Song1f93fa52020-11-20 13:57:39 +08008673 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308674
Varun Balaraje49253e2017-07-06 19:48:56 +05308675 if (is_interactive_usecase(out->usecase))
8676 free_interactive_usecase(adev, out->usecase);
8677
Ashish Jain83a6cc22016-06-28 14:34:17 +05308678 if (out->convert_buffer != NULL) {
8679 free(out->convert_buffer);
8680 out->convert_buffer = NULL;
8681 }
8682
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008683 if (adev->voice_tx_output == out)
8684 adev->voice_tx_output = NULL;
8685
Aalique Grahame22e49102018-12-18 14:23:57 -08008686 error_log_destroy(out->error_log);
8687 out->error_log = NULL;
8688
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308689 if (adev->primary_output == out)
8690 adev->primary_output = NULL;
8691
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008692 pthread_cond_destroy(&out->cond);
8693 pthread_mutex_destroy(&out->lock);
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008694 pthread_mutex_destroy(&out->pre_lock);
8695 pthread_mutex_destroy(&out->latch_lock);
8696 pthread_mutex_destroy(&out->position_query_lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008697
8698 pthread_mutex_lock(&adev->lock);
8699 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8700 if (out_ctxt != NULL) {
8701 list_remove(&out_ctxt->list);
8702 free(out_ctxt);
8703 } else {
8704 ALOGW("%s, output stream already closed", __func__);
8705 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008706 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008707 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008708 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008709}
8710
8711static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8712{
8713 struct audio_device *adev = (struct audio_device *)dev;
8714 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008715 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008716 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008717 int ret;
8718 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008719 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008720 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008721 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008722
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008723 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008724 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008725
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308726 if (!parms)
8727 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308728
Derek Chen6f293672019-04-01 01:40:24 -07008729 /* notify adev and input/output streams on the snd card status */
8730 adev_snd_mon_cb((void *)adev, parms);
8731
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008732 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
8733 if (ret >= 0) {
8734 list_for_each(node, &adev->active_outputs_list) {
8735 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8736 streams_output_ctxt_t,
8737 list);
8738 out_snd_mon_cb((void *)out_ctxt->output, parms);
8739 }
Derek Chen6f293672019-04-01 01:40:24 -07008740
Weiyin Jiangd4e8ced2020-12-22 14:35:46 +08008741 list_for_each(node, &adev->active_inputs_list) {
8742 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8743 streams_input_ctxt_t,
8744 list);
8745 in_snd_mon_cb((void *)in_ctxt->input, parms);
8746 }
Derek Chen6f293672019-04-01 01:40:24 -07008747 }
8748
Zhou Songd6d71752019-05-21 18:08:51 +08008749 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308750 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8751 if (ret >= 0) {
8752 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008753 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308754 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008755 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308756 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008757 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008758 }
8759 }
8760
8761 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008762 if (ret >= 0) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008763 if (!strncmp(value, "false", 5) &&
8764 audio_extn_a2dp_source_is_suspended()) {
8765 struct audio_usecase *usecase;
8766 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008767 list_for_each(node, &adev->usecase_list) {
8768 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008769 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008770 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008771 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008772 reassign_device_list(&usecase->stream.in->device_list,
8773 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008774 select_devices(adev, usecase->id);
8775 }
Zhou Songd6d71752019-05-21 18:08:51 +08008776 }
8777 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308778 }
8779
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008780 status = voice_set_parameters(adev, parms);
8781 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008782 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008783
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008784 status = platform_set_parameters(adev->platform, parms);
8785 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008786 goto done;
8787
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008788 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8789 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008790 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008791 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8792 adev->bluetooth_nrec = true;
8793 else
8794 adev->bluetooth_nrec = false;
8795 }
8796
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008797 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8798 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008799 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8800 adev->screen_off = false;
8801 else
8802 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008803 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008804 }
8805
Eric Laurent4b084132018-10-19 17:33:43 -07008806 ret = str_parms_get_int(parms, "rotation", &val);
8807 if (ret >= 0) {
8808 bool reverse_speakers = false;
8809 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8810 switch (val) {
8811 // FIXME: note that the code below assumes that the speakers are in the correct placement
8812 // relative to the user when the device is rotated 90deg from its default rotation. This
8813 // assumption is device-specific, not platform-specific like this code.
8814 case 270:
8815 reverse_speakers = true;
8816 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8817 break;
8818 case 0:
8819 case 180:
8820 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8821 break;
8822 case 90:
8823 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8824 break;
8825 default:
8826 ALOGE("%s: unexpected rotation of %d", __func__, val);
8827 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008828 }
Eric Laurent4b084132018-10-19 17:33:43 -07008829 if (status == 0) {
8830 // check and set swap
8831 // - check if orientation changed and speaker active
8832 // - set rotation and cache the rotation value
8833 adev->camera_orientation =
8834 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8835 if (!audio_extn_is_maxx_audio_enabled())
8836 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8837 }
8838 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008839
Mingming Yin514a8bc2014-07-29 15:22:21 -07008840 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8841 if (ret >= 0) {
8842 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8843 adev->bt_wb_speech_enabled = true;
8844 else
8845 adev->bt_wb_speech_enabled = false;
8846 }
8847
Zhou Song12c29502019-03-16 10:37:18 +08008848 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8849 if (ret >= 0) {
8850 val = atoi(value);
8851 adev->swb_speech_mode = val;
8852 }
8853
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008854 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8855 if (ret >= 0) {
8856 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308857 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008858 if (audio_is_output_device(val) &&
8859 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008860 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008861 platform_get_controller_stream_from_params(parms, &controller, &stream);
8862 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8863 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008864 if (ret < 0) {
8865 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308866 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008867 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008868 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308869 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008870 /*
8871 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8872 * Per AudioPolicyManager, USB device is higher priority than WFD.
8873 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8874 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8875 * starting voice call on USB
8876 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008877 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308878 if (ret >= 0)
8879 audio_extn_usb_add_device(device, atoi(value));
8880
Zhou Song6f862822017-11-06 17:27:57 +08008881 if (!audio_extn_usb_is_tunnel_supported()) {
8882 ALOGV("detected USB connect .. disable proxy");
8883 adev->allow_afe_proxy_usage = false;
8884 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008885 }
8886 }
8887
8888 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8889 if (ret >= 0) {
8890 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308891 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008892 /*
8893 * The HDMI / Displayport disconnect handling has been moved to
8894 * audio extension to ensure that its parameters are not
8895 * invalidated prior to updating sysfs of the disconnect event
8896 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8897 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308898 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008899 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308900 if (ret >= 0)
8901 audio_extn_usb_remove_device(device, atoi(value));
8902
Zhou Song6f862822017-11-06 17:27:57 +08008903 if (!audio_extn_usb_is_tunnel_supported()) {
8904 ALOGV("detected USB disconnect .. enable proxy");
8905 adev->allow_afe_proxy_usage = true;
8906 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008907 }
8908 }
8909
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008910 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008911
8912 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008913 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308914 struct audio_usecase *usecase;
8915 struct listnode *node;
8916 list_for_each(node, &adev->usecase_list) {
8917 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008918 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8919 continue;
8920
8921 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308922 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308923 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308924 ALOGD("Switching to speaker and muting the stream before select_devices");
8925 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308926 //force device switch to re configure encoder
8927 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308928 ALOGD("Unmuting the stream after select_devices");
Zhou Song1f93fa52020-11-20 13:57:39 +08008929 check_a2dp_restore_l(adev, usecase->stream.out, true);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308930 audio_extn_a2dp_set_handoff_mode(false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308931 break;
Zhou Song9ebf6792020-09-23 22:49:01 +08008932 } else if (is_offload_usecase(usecase->stream.out->usecase)) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008933 pthread_mutex_lock(&usecase->stream.out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +08008934 if (usecase->stream.out->a2dp_muted) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +08008935 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
8936 reassign_device_list(&usecase->stream.out->device_list,
8937 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
8938 check_a2dp_restore_l(adev, usecase->stream.out, true);
8939 break;
8940 }
8941 pthread_mutex_unlock(&usecase->stream.out->latch_lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308942 }
8943 }
8944 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008945
8946 //handle vr audio setparam
8947 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8948 value, sizeof(value));
8949 if (ret >= 0) {
8950 ALOGI("Setting vr mode to be %s", value);
8951 if (!strncmp(value, "true", 4)) {
8952 adev->vr_audio_mode_enabled = true;
8953 ALOGI("Setting vr mode to true");
8954 } else if (!strncmp(value, "false", 5)) {
8955 adev->vr_audio_mode_enabled = false;
8956 ALOGI("Setting vr mode to false");
8957 } else {
8958 ALOGI("wrong vr mode set");
8959 }
8960 }
8961
Eric Laurent4b084132018-10-19 17:33:43 -07008962 //FIXME: to be replaced by proper video capture properties API
8963 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8964 if (ret >= 0) {
8965 int camera_facing = CAMERA_FACING_BACK;
8966 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8967 camera_facing = CAMERA_FACING_FRONT;
8968 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8969 camera_facing = CAMERA_FACING_BACK;
8970 else {
8971 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8972 goto done;
8973 }
8974 adev->camera_orientation =
8975 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8976 struct audio_usecase *usecase;
8977 struct listnode *node;
8978 list_for_each(node, &adev->usecase_list) {
8979 usecase = node_to_item(node, struct audio_usecase, list);
8980 struct stream_in *in = usecase->stream.in;
8981 if (usecase->type == PCM_CAPTURE && in != NULL &&
8982 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8983 select_devices(adev, in->usecase);
8984 }
8985 }
8986 }
8987
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308988 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008989done:
8990 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008991 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308992error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008993 ALOGV("%s: exit with code(%d)", __func__, status);
8994 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008995}
8996
8997static char* adev_get_parameters(const struct audio_hw_device *dev,
8998 const char *keys)
8999{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309000 ALOGD("%s:%s", __func__, keys);
9001
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009002 struct audio_device *adev = (struct audio_device *)dev;
9003 struct str_parms *reply = str_parms_create();
9004 struct str_parms *query = str_parms_create_str(keys);
9005 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05309006 char value[256] = {0};
9007 int ret = 0;
9008
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009009 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08009010 if (reply) {
9011 str_parms_destroy(reply);
9012 }
9013 if (query) {
9014 str_parms_destroy(query);
9015 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009016 ALOGE("adev_get_parameters: failed to create query or reply");
9017 return NULL;
9018 }
9019
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009020 //handle vr audio getparam
9021
9022 ret = str_parms_get_str(query,
9023 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9024 value, sizeof(value));
9025
9026 if (ret >= 0) {
9027 bool vr_audio_enabled = false;
9028 pthread_mutex_lock(&adev->lock);
9029 vr_audio_enabled = adev->vr_audio_mode_enabled;
9030 pthread_mutex_unlock(&adev->lock);
9031
9032 ALOGI("getting vr mode to %d", vr_audio_enabled);
9033
9034 if (vr_audio_enabled) {
9035 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9036 "true");
9037 goto exit;
9038 } else {
9039 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
9040 "false");
9041 goto exit;
9042 }
9043 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009044
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009045 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009046 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08009047 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08009048 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009049 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08009050 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05309051 pthread_mutex_unlock(&adev->lock);
9052
Naresh Tannirud7205b62014-06-20 02:54:48 +05309053exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009054 str = str_parms_to_str(reply);
9055 str_parms_destroy(query);
9056 str_parms_destroy(reply);
9057
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05309058 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009059 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009060}
9061
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009062static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009063{
9064 return 0;
9065}
9066
9067static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9068{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009069 int ret;
9070 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009071
9072 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9073
Haynes Mathew George5191a852013-09-11 14:19:36 -07009074 pthread_mutex_lock(&adev->lock);
9075 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009076 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009077 pthread_mutex_unlock(&adev->lock);
9078 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009079}
9080
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009081static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9082 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009083{
9084 return -ENOSYS;
9085}
9086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009087static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9088 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009089{
9090 return -ENOSYS;
9091}
9092
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009093static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9094 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009095{
9096 return -ENOSYS;
9097}
9098
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009099static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9100 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009101{
9102 return -ENOSYS;
9103}
9104
9105static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9106{
9107 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009108 struct listnode *node;
9109 struct audio_usecase *usecase = NULL;
9110 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112 pthread_mutex_lock(&adev->lock);
9113 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309114 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9115 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009116 adev->mode = mode;
Weiyin Jiangc3a9c812020-09-22 16:48:19 +08009117 if (mode == AUDIO_MODE_CALL_SCREEN) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309118 adev->current_call_output = adev->primary_output;
9119 voice_start_call(adev);
9120 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009121 (mode == AUDIO_MODE_NORMAL ||
9122 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009123 list_for_each(node, &adev->usecase_list) {
9124 usecase = node_to_item(node, struct audio_usecase, list);
9125 if (usecase->type == VOICE_CALL)
9126 break;
9127 }
9128 if (usecase &&
9129 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9130 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9131 true);
9132 if (ret != 0) {
9133 /* default service interval was successfully updated,
9134 reopen USB backend with new service interval */
9135 check_usecases_codec_backend(adev,
9136 usecase,
9137 usecase->out_snd_device);
9138 }
9139 }
9140
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009141 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009142 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009143 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009144 // restore device for other active usecases after stop call
9145 list_for_each(node, &adev->usecase_list) {
9146 usecase = node_to_item(node, struct audio_usecase, list);
9147 select_devices(adev, usecase->id);
9148 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009150 }
9151 pthread_mutex_unlock(&adev->lock);
9152 return 0;
9153}
9154
9155static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9156{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009157 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009158 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009159
9160 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009161 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009162 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009163
Derek Chend2530072014-11-24 12:39:14 -08009164 if (adev->ext_hw_plugin)
9165 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009166
9167 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009168 pthread_mutex_unlock(&adev->lock);
9169
9170 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171}
9172
9173static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9174{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009175 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176 return 0;
9177}
9178
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009179static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009180 const struct audio_config *config)
9181{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009182 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009183
Aalique Grahame22e49102018-12-18 14:23:57 -08009184 /* Don't know if USB HIFI in this context so use true to be conservative */
9185 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9186 true /*is_usb_hifi */) != 0)
9187 return 0;
9188
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009189 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9190 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009191}
9192
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009193static bool adev_input_allow_hifi_record(struct audio_device *adev,
9194 audio_devices_t devices,
9195 audio_input_flags_t flags,
9196 audio_source_t source) {
9197 const bool allowed = true;
9198
9199 if (!audio_is_usb_in_device(devices))
9200 return !allowed;
9201
9202 switch (flags) {
9203 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009204 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009205 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9206 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009207 default:
9208 return !allowed;
9209 }
9210
9211 switch (source) {
9212 case AUDIO_SOURCE_DEFAULT:
9213 case AUDIO_SOURCE_MIC:
9214 case AUDIO_SOURCE_UNPROCESSED:
9215 break;
9216 default:
9217 return !allowed;
9218 }
9219
9220 switch (adev->mode) {
9221 case 0:
9222 break;
9223 default:
9224 return !allowed;
9225 }
9226
9227 return allowed;
9228}
9229
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009230static int adev_update_voice_comm_input_stream(struct stream_in *in,
9231 struct audio_config *config)
9232{
9233 bool valid_rate = (config->sample_rate == 8000 ||
9234 config->sample_rate == 16000 ||
9235 config->sample_rate == 32000 ||
9236 config->sample_rate == 48000);
9237 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9238
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009239 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009240 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009241 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9242 in->config = default_pcm_config_voip_copp;
9243 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9244 DEFAULT_VOIP_BUF_DURATION_MS,
9245 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009246 } else {
9247 ALOGW("%s No valid input in voip, use defaults"
9248 "sample rate %u, channel mask 0x%X",
9249 __func__, config->sample_rate, in->channel_mask);
9250 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009251 in->config.rate = config->sample_rate;
9252 in->sample_rate = config->sample_rate;
9253 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009254 //XXX needed for voice_extn_compress_voip_open_input_stream
9255 in->config.rate = config->sample_rate;
9256 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309257 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009258 voice_extn_compress_voip_is_active(in->dev)) &&
9259 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9260 valid_rate && valid_ch) {
9261 voice_extn_compress_voip_open_input_stream(in);
9262 // update rate entries to match config from AF
9263 in->config.rate = config->sample_rate;
9264 in->sample_rate = config->sample_rate;
9265 } else {
9266 ALOGW("%s compress voip not active, use defaults", __func__);
9267 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009268 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009269 return 0;
9270}
9271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009272static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009273 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009274 audio_devices_t devices,
9275 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009276 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309277 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009278 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009279 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009280{
9281 struct audio_device *adev = (struct audio_device *)dev;
9282 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009283 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009284 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009285 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309286 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009287 bool is_usb_dev = audio_is_usb_in_device(devices);
9288 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9289 devices,
9290 flags,
9291 source);
Andy Hung94320602018-10-29 18:31:12 -07009292 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9293 " sample_rate %u, channel_mask %#x, format %#x",
9294 __func__, flags, is_usb_dev, may_use_hifi_record,
9295 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309296
kunleizdff872d2018-08-20 14:40:33 +08009297 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009298 is_usb_dev = false;
9299 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9300 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9301 __func__, devices);
9302 }
9303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009304 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009305
9306 if (!(is_usb_dev && may_use_hifi_record)) {
9307 if (config->sample_rate == 0)
9308 config->sample_rate = 48000;
9309 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9310 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9311 if (config->format == AUDIO_FORMAT_DEFAULT)
9312 config->format = AUDIO_FORMAT_PCM_16_BIT;
9313
9314 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9315
Aalique Grahame22e49102018-12-18 14:23:57 -08009316 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9317 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009318 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009320
Rahul Sharma99770982019-03-06 17:05:26 +05309321 pthread_mutex_lock(&adev->lock);
9322 if (in_get_stream(adev, handle) != NULL) {
9323 ALOGW("%s, input stream already opened", __func__);
9324 ret = -EEXIST;
9325 }
9326 pthread_mutex_unlock(&adev->lock);
9327 if (ret)
9328 return ret;
9329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009330 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009331
9332 if (!in) {
9333 ALOGE("failed to allocate input stream");
9334 return -ENOMEM;
9335 }
9336
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309337 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309338 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9339 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009340 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009341 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009343 in->stream.common.get_sample_rate = in_get_sample_rate;
9344 in->stream.common.set_sample_rate = in_set_sample_rate;
9345 in->stream.common.get_buffer_size = in_get_buffer_size;
9346 in->stream.common.get_channels = in_get_channels;
9347 in->stream.common.get_format = in_get_format;
9348 in->stream.common.set_format = in_set_format;
9349 in->stream.common.standby = in_standby;
9350 in->stream.common.dump = in_dump;
9351 in->stream.common.set_parameters = in_set_parameters;
9352 in->stream.common.get_parameters = in_get_parameters;
9353 in->stream.common.add_audio_effect = in_add_audio_effect;
9354 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9355 in->stream.set_gain = in_set_gain;
9356 in->stream.read = in_read;
9357 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009358 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309359 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009360 in->stream.set_microphone_direction = in_set_microphone_direction;
9361 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009362 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009363
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009364 list_init(&in->device_list);
9365 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009366 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009367 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009368 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009369 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009370 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009371 in->bit_width = 16;
9372 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009373 in->direction = MIC_DIRECTION_UNSPECIFIED;
9374 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009375 list_init(&in->aec_list);
9376 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009377 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009378
Andy Hung94320602018-10-29 18:31:12 -07009379 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009380 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9381 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9382 /* Force channel config requested to mono if incall
9383 record is being requested for only uplink/downlink */
9384 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9385 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9386 ret = -EINVAL;
9387 goto err_open;
9388 }
9389 }
9390
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009391 if (is_usb_dev && may_use_hifi_record) {
9392 /* HiFi record selects an appropriate format, channel, rate combo
9393 depending on sink capabilities*/
9394 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9395 &config->format,
9396 &in->supported_formats[0],
9397 MAX_SUPPORTED_FORMATS,
9398 &config->channel_mask,
9399 &in->supported_channel_masks[0],
9400 MAX_SUPPORTED_CHANNEL_MASKS,
9401 &config->sample_rate,
9402 &in->supported_sample_rates[0],
9403 MAX_SUPPORTED_SAMPLE_RATES);
9404 if (ret != 0) {
9405 ret = -EINVAL;
9406 goto err_open;
9407 }
9408 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009409 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309410 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309411 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9412 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9413 in->config.format = PCM_FORMAT_S32_LE;
9414 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309415 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9416 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9417 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9418 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9419 bool ret_error = false;
9420 in->bit_width = 24;
9421 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9422 from HAL is 24_packed and 8_24
9423 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9424 24_packed return error indicating supported format is 24_packed
9425 *> In case of any other source requesting 24 bit or float return error
9426 indicating format supported is 16 bit only.
9427
9428 on error flinger will retry with supported format passed
9429 */
9430 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9431 (source != AUDIO_SOURCE_CAMCORDER)) {
9432 config->format = AUDIO_FORMAT_PCM_16_BIT;
9433 if (config->sample_rate > 48000)
9434 config->sample_rate = 48000;
9435 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009436 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9437 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309438 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9439 ret_error = true;
9440 }
9441
9442 if (ret_error) {
9443 ret = -EINVAL;
9444 goto err_open;
9445 }
9446 }
9447
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009448 in->channel_mask = config->channel_mask;
9449 in->format = config->format;
9450
9451 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309452
9453 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9454 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9455 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9456 else {
9457 ret = -EINVAL;
9458 goto err_open;
9459 }
9460 }
9461
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009462 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309463 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9464 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009465 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9466 is_low_latency = true;
9467#if LOW_LATENCY_CAPTURE_USE_CASE
9468 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9469#endif
9470 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009471 if (!in->realtime) {
9472 in->config = pcm_config_audio_capture;
9473 frame_size = audio_stream_in_frame_size(&in->stream);
9474 buffer_size = get_input_buffer_size(config->sample_rate,
9475 config->format,
9476 channel_count,
9477 is_low_latency);
9478 in->config.period_size = buffer_size / frame_size;
9479 in->config.rate = config->sample_rate;
9480 in->af_period_multiplier = 1;
9481 } else {
9482 // period size is left untouched for rt mode playback
9483 in->config = pcm_config_audio_capture_rt;
9484 in->af_period_multiplier = af_period_multiplier;
9485 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009486 }
9487
9488 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9489 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9490 in->realtime = 0;
9491 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9492 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009493 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009494 in->stream.start = in_start;
9495 in->stream.stop = in_stop;
9496 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9497 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009498 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009499 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009500 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9501 in->config = pcm_config_audio_capture;
9502 frame_size = audio_stream_in_frame_size(&in->stream);
9503 buffer_size = get_input_buffer_size(config->sample_rate,
9504 config->format,
9505 channel_count,
9506 false /*is_low_latency*/);
9507 in->config.period_size = buffer_size / frame_size;
9508 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009509 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009510 switch (config->format) {
9511 case AUDIO_FORMAT_PCM_32_BIT:
9512 in->bit_width = 32;
9513 break;
9514 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9515 case AUDIO_FORMAT_PCM_8_24_BIT:
9516 in->bit_width = 24;
9517 break;
9518 default:
9519 in->bit_width = 16;
9520 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009521 } else if (is_single_device_type_equal(&in->device_list,
9522 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9523 is_single_device_type_equal(&in->device_list,
9524 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009525 if (config->sample_rate == 0)
9526 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9527 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9528 config->sample_rate != 8000) {
9529 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9530 ret = -EINVAL;
9531 goto err_open;
9532 }
9533 if (config->format == AUDIO_FORMAT_DEFAULT)
9534 config->format = AUDIO_FORMAT_PCM_16_BIT;
9535 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9536 config->format = AUDIO_FORMAT_PCM_16_BIT;
9537 ret = -EINVAL;
9538 goto err_open;
9539 }
9540
9541 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009542 if (adev->ha_proxy_enable &&
9543 is_single_device_type_equal(&in->device_list,
9544 AUDIO_DEVICE_IN_TELEPHONY_RX))
9545 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009546 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009547 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009548 in->af_period_multiplier = 1;
9549 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
Shalini Manjunathaabdf7482020-01-03 15:00:14 +05309550 (!voice_extn_is_compress_voip_supported()) &&
Aalique Grahame22e49102018-12-18 14:23:57 -08009551 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9552 (config->sample_rate == 8000 ||
9553 config->sample_rate == 16000 ||
9554 config->sample_rate == 32000 ||
9555 config->sample_rate == 48000) &&
9556 channel_count == 1) {
9557 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9558 in->config = pcm_config_audio_capture;
9559 frame_size = audio_stream_in_frame_size(&in->stream);
9560 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9561 config->sample_rate,
9562 config->format,
9563 channel_count, false /*is_low_latency*/);
9564 in->config.period_size = buffer_size / frame_size;
9565 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9566 in->config.rate = config->sample_rate;
9567 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009568 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309569 int ret_val;
9570 pthread_mutex_lock(&adev->lock);
9571 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9572 in, config, &channel_mask_updated);
9573 pthread_mutex_unlock(&adev->lock);
9574
9575 if (!ret_val) {
9576 if (channel_mask_updated == true) {
9577 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9578 __func__, config->channel_mask);
9579 ret = -EINVAL;
9580 goto err_open;
9581 }
9582 ALOGD("%s: created multi-channel session succesfully",__func__);
9583 } else if (audio_extn_compr_cap_enabled() &&
9584 audio_extn_compr_cap_format_supported(config->format) &&
9585 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9586 audio_extn_compr_cap_init(in);
9587 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309588 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309589 if (ret)
9590 goto err_open;
9591 } else {
9592 in->config = pcm_config_audio_capture;
9593 in->config.rate = config->sample_rate;
9594 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309595 in->format = config->format;
9596 frame_size = audio_stream_in_frame_size(&in->stream);
9597 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009598 config->format,
9599 channel_count,
9600 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009601 /* prevent division-by-zero */
9602 if (frame_size == 0) {
9603 ALOGE("%s: Error frame_size==0", __func__);
9604 ret = -EINVAL;
9605 goto err_open;
9606 }
9607
Revathi Uddarajud2634032017-12-07 14:42:34 +05309608 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009609 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009610
Revathi Uddarajud2634032017-12-07 14:42:34 +05309611 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9612 /* optionally use VOIP usecase depending on config(s) */
9613 ret = adev_update_voice_comm_input_stream(in, config);
9614 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009615
Revathi Uddarajud2634032017-12-07 14:42:34 +05309616 if (ret) {
9617 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9618 goto err_open;
9619 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009620 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309621
9622 /* assign concurrent capture usecase if record has to caried out from
9623 * actual hardware input source */
9624 if (audio_extn_is_concurrent_capture_enabled() &&
9625 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309626 /* Acquire lock to avoid two concurrent use cases initialized to
9627 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009628
Samyak Jainc37062f2019-04-25 18:41:06 +05309629 if (in->usecase == USECASE_AUDIO_RECORD) {
9630 pthread_mutex_lock(&adev->lock);
9631 if (!(adev->pcm_record_uc_state)) {
9632 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9633 adev->pcm_record_uc_state = 1;
9634 pthread_mutex_unlock(&adev->lock);
9635 } else {
9636 pthread_mutex_unlock(&adev->lock);
9637 /* Assign compress record use case for second record */
9638 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9639 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9640 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9641 if (audio_extn_cin_applicable_stream(in)) {
9642 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309643 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309644 if (ret)
9645 goto err_open;
9646 }
9647 }
9648 }
kunleiz28c73e72019-03-27 17:24:04 +08009649 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009650 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309651 if (audio_extn_ssr_get_stream() != in)
9652 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009653
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009654 in->sample_rate = in->config.rate;
9655
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309656 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9657 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009658 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009659 in->sample_rate, in->bit_width,
9660 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309661 register_format(in->format, in->supported_formats);
9662 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9663 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309664
Aalique Grahame22e49102018-12-18 14:23:57 -08009665 in->error_log = error_log_create(
9666 ERROR_LOG_ENTRIES,
9667 1000000000 /* aggregate consecutive identical errors within one second */);
9668
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009669 /* This stream could be for sound trigger lab,
9670 get sound trigger pcm if present */
9671 audio_extn_sound_trigger_check_and_get_session(in);
9672
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309673 lock_input_stream(in);
9674 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9675 pthread_mutex_lock(&adev->lock);
9676 in->card_status = adev->card_status;
9677 pthread_mutex_unlock(&adev->lock);
9678 pthread_mutex_unlock(&in->lock);
9679
Aalique Grahame22e49102018-12-18 14:23:57 -08009680 stream_app_type_cfg_init(&in->app_type_cfg);
9681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009682 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009683
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009684 ret = io_streams_map_insert(adev, &in->stream.common,
9685 handle, AUDIO_PATCH_HANDLE_NONE);
9686 if (ret != 0)
9687 goto err_open;
9688
Derek Chenf939fb72018-11-13 13:34:41 -08009689 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9690 calloc(1, sizeof(streams_input_ctxt_t));
9691 if (in_ctxt == NULL) {
9692 ALOGE("%s fail to allocate input ctxt", __func__);
9693 ret = -ENOMEM;
9694 goto err_open;
9695 }
9696 in_ctxt->input = in;
9697
9698 pthread_mutex_lock(&adev->lock);
9699 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9700 pthread_mutex_unlock(&adev->lock);
9701
Eric Laurent994a6932013-07-17 11:51:42 -07009702 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009703 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009704
9705err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309706 if (in->usecase == USECASE_AUDIO_RECORD) {
9707 pthread_mutex_lock(&adev->lock);
9708 adev->pcm_record_uc_state = 0;
9709 pthread_mutex_unlock(&adev->lock);
9710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009711 free(in);
9712 *stream_in = NULL;
9713 return ret;
9714}
9715
9716static void adev_close_input_stream(struct audio_hw_device *dev,
9717 struct audio_stream_in *stream)
9718{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009719 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009720 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009721 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309722
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309723 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009724
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009725 if (in == NULL) {
9726 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9727 return;
9728 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009729 io_streams_map_remove(adev, in->capture_handle);
9730
kunleiz70e57612018-12-28 17:50:23 +08009731 /* must deregister from sndmonitor first to prevent races
9732 * between the callback and close_stream
9733 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309734 audio_extn_snd_mon_unregister_listener(stream);
9735
kunleiz70e57612018-12-28 17:50:23 +08009736 /* Disable echo reference if there are no active input, hfp call
9737 * and sound trigger while closing input stream
9738 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009739 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009740 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009741 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9742 struct listnode out_devices;
9743 list_init(&out_devices);
9744 platform_set_echo_reference(adev, false, &out_devices);
9745 } else
kunleiz70e57612018-12-28 17:50:23 +08009746 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309747
Weiyin Jiang2995f662019-04-17 14:25:12 +08009748 error_log_destroy(in->error_log);
9749 in->error_log = NULL;
9750
Pallavid7c7a272018-01-16 11:22:55 +05309751
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009752 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309753 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009754 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309755 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009756 if (ret != 0)
9757 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9758 __func__, ret);
9759 } else
9760 in_standby(&stream->common);
9761
Weiyin Jiangd5974e62020-09-08 20:28:22 +08009762 pthread_mutex_destroy(&in->lock);
9763 pthread_mutex_destroy(&in->pre_lock);
9764
Revathi Uddarajud2634032017-12-07 14:42:34 +05309765 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309766 if (in->usecase == USECASE_AUDIO_RECORD) {
9767 adev->pcm_record_uc_state = 0;
9768 }
9769
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009770 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9771 adev->enable_voicerx = false;
9772 }
9773
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009774 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009775 audio_extn_ssr_deinit();
9776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009777
Garmond Leunge2433c32017-09-28 21:51:22 -07009778 if (audio_extn_ffv_get_stream() == in) {
9779 audio_extn_ffv_stream_deinit();
9780 }
9781
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309782 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009783 audio_extn_compr_cap_format_supported(in->config.format))
9784 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309785
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309786 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309787 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009788
Mingming Yinfd7607b2016-01-22 12:48:44 -08009789 if (in->is_st_session) {
9790 ALOGV("%s: sound trigger pcm stop lab", __func__);
9791 audio_extn_sound_trigger_stop_lab(in);
9792 }
Derek Chenf939fb72018-11-13 13:34:41 -08009793 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9794 if (in_ctxt != NULL) {
9795 list_remove(&in_ctxt->list);
9796 free(in_ctxt);
9797 } else {
9798 ALOGW("%s, input stream already closed", __func__);
9799 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009800 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009802 return;
9803}
9804
Aalique Grahame22e49102018-12-18 14:23:57 -08009805/* verifies input and output devices and their capabilities.
9806 *
9807 * This verification is required when enabling extended bit-depth or
9808 * sampling rates, as not all qcom products support it.
9809 *
9810 * Suitable for calling only on initialization such as adev_open().
9811 * It fills the audio_device use_case_table[] array.
9812 *
9813 * Has a side-effect that it needs to configure audio routing / devices
9814 * in order to power up the devices and read the device parameters.
9815 * It does not acquire any hw device lock. Should restore the devices
9816 * back to "normal state" upon completion.
9817 */
9818static int adev_verify_devices(struct audio_device *adev)
9819{
9820 /* enumeration is a bit difficult because one really wants to pull
9821 * the use_case, device id, etc from the hidden pcm_device_table[].
9822 * In this case there are the following use cases and device ids.
9823 *
9824 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9825 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9826 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9827 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9828 * [USECASE_AUDIO_RECORD] = {0, 0},
9829 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9830 * [USECASE_VOICE_CALL] = {2, 2},
9831 *
9832 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9833 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9834 */
9835
9836 /* should be the usecases enabled in adev_open_input_stream() */
9837 static const int test_in_usecases[] = {
9838 USECASE_AUDIO_RECORD,
9839 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9840 };
9841 /* should be the usecases enabled in adev_open_output_stream()*/
9842 static const int test_out_usecases[] = {
9843 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9844 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9845 };
9846 static const usecase_type_t usecase_type_by_dir[] = {
9847 PCM_PLAYBACK,
9848 PCM_CAPTURE,
9849 };
9850 static const unsigned flags_by_dir[] = {
9851 PCM_OUT,
9852 PCM_IN,
9853 };
9854
9855 size_t i;
9856 unsigned dir;
9857 const unsigned card_id = adev->snd_card;
9858
9859 for (dir = 0; dir < 2; ++dir) {
9860 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9861 const unsigned flags_dir = flags_by_dir[dir];
9862 const size_t testsize =
9863 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9864 const int *testcases =
9865 dir ? test_in_usecases : test_out_usecases;
9866 const audio_devices_t audio_device =
9867 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9868
9869 for (i = 0; i < testsize; ++i) {
9870 const audio_usecase_t audio_usecase = testcases[i];
9871 int device_id;
9872 struct pcm_params **pparams;
9873 struct stream_out out;
9874 struct stream_in in;
9875 struct audio_usecase uc_info;
9876 int retval;
9877
9878 pparams = &adev->use_case_table[audio_usecase];
9879 pcm_params_free(*pparams); /* can accept null input */
9880 *pparams = NULL;
9881
9882 /* find the device ID for the use case (signed, for error) */
9883 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9884 if (device_id < 0)
9885 continue;
9886
9887 /* prepare structures for device probing */
9888 memset(&uc_info, 0, sizeof(uc_info));
9889 uc_info.id = audio_usecase;
9890 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009891 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009892 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009893 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009894 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009895 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009896 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9897 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009898 }
9899 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009900 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009901 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009902 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009903 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009904 uc_info.in_snd_device = SND_DEVICE_NONE;
9905 uc_info.out_snd_device = SND_DEVICE_NONE;
9906 list_add_tail(&adev->usecase_list, &uc_info.list);
9907
9908 /* select device - similar to start_(in/out)put_stream() */
9909 retval = select_devices(adev, audio_usecase);
9910 if (retval >= 0) {
9911 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9912#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009913 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009914 if (*pparams) {
9915 ALOGV("%s: (%s) card %d device %d", __func__,
9916 dir ? "input" : "output", card_id, device_id);
9917 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9918 } else {
9919 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9920 }
9921#endif
9922 }
9923
9924 /* deselect device - similar to stop_(in/out)put_stream() */
9925 /* 1. Get and set stream specific mixer controls */
9926 retval = disable_audio_route(adev, &uc_info);
9927 /* 2. Disable the rx device */
9928 retval = disable_snd_device(adev,
9929 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9930 list_remove(&uc_info.list);
9931 }
9932 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009933 return 0;
9934}
9935
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009936int update_patch(unsigned int num_sources,
9937 const struct audio_port_config *sources,
9938 unsigned int num_sinks,
9939 const struct audio_port_config *sinks,
9940 audio_patch_handle_t handle,
9941 struct audio_patch_info *p_info,
9942 patch_type_t patch_type, bool new_patch)
9943{
9944 ALOGD("%s: enter", __func__);
9945
9946 if (p_info == NULL) {
9947 ALOGE("%s: Invalid patch pointer", __func__);
9948 return -EINVAL;
9949 }
9950
9951 if (new_patch) {
9952 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9953 if (p_info->patch == NULL) {
9954 ALOGE("%s: Could not allocate patch", __func__);
9955 return -ENOMEM;
9956 }
9957 }
9958
9959 p_info->patch->id = handle;
9960 p_info->patch->num_sources = num_sources;
9961 p_info->patch->num_sinks = num_sinks;
9962
9963 for (int i = 0; i < num_sources; i++)
9964 p_info->patch->sources[i] = sources[i];
9965 for (int i = 0; i < num_sinks; i++)
9966 p_info->patch->sinks[i] = sinks[i];
9967
9968 p_info->patch_type = patch_type;
9969 return 0;
9970}
9971
9972audio_patch_handle_t generate_patch_handle()
9973{
9974 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9975 if (++patch_handle < 0)
9976 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9977 return patch_handle;
9978}
9979
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309980int adev_create_audio_patch(struct audio_hw_device *dev,
9981 unsigned int num_sources,
9982 const struct audio_port_config *sources,
9983 unsigned int num_sinks,
9984 const struct audio_port_config *sinks,
9985 audio_patch_handle_t *handle)
9986{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009987 int ret = 0;
9988 struct audio_device *adev = (struct audio_device *)dev;
9989 struct audio_patch_info *p_info = NULL;
9990 patch_type_t patch_type = PATCH_NONE;
9991 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9992 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9993 struct audio_stream_info *s_info = NULL;
9994 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009995 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009996 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9997 bool new_patch = false;
9998 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309999
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010000 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
10001 num_sources, num_sinks, *handle);
10002
10003 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
10004 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
10005 ALOGE("%s: Invalid patch arguments", __func__);
10006 ret = -EINVAL;
10007 goto done;
10008 }
10009
10010 if (num_sources > 1) {
10011 ALOGE("%s: Multiple sources are not supported", __func__);
10012 ret = -EINVAL;
10013 goto done;
10014 }
10015
10016 if (sources == NULL || sinks == NULL) {
10017 ALOGE("%s: Invalid sources or sinks port config", __func__);
10018 ret = -EINVAL;
10019 goto done;
10020 }
10021
10022 ALOGV("%s: source role %d, source type %d", __func__,
10023 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010024 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025
10026 // Populate source/sink information and fetch stream info
10027 switch (sources[0].type) {
10028 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
10029 device_type = sources[0].ext.device.type;
10030 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010031 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
10033 patch_type = PATCH_CAPTURE;
10034 io_handle = sinks[0].ext.mix.handle;
10035 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010036 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010037 __func__, device_type, io_handle);
10038 } else {
10039 // Device to device patch is not implemented.
10040 // This space will need changes if audio HAL
10041 // handles device to device patches in the future.
10042 patch_type = PATCH_DEVICE_LOOPBACK;
10043 }
10044 break;
10045 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
10046 io_handle = sources[0].ext.mix.handle;
10047 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010048 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010050 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 }
10052 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010053 ALOGD("%s: Playback patch from mix handle %d to device %x",
10054 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010055 break;
10056 case AUDIO_PORT_TYPE_SESSION:
10057 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010058 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
10059 ret = -EINVAL;
10060 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010061 }
10062
10063 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010064
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010065 // Generate patch info and update patch
10066 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010067 *handle = generate_patch_handle();
10068 p_info = (struct audio_patch_info *)
10069 calloc(1, sizeof(struct audio_patch_info));
10070 if (p_info == NULL) {
10071 ALOGE("%s: Failed to allocate memory", __func__);
10072 pthread_mutex_unlock(&adev->lock);
10073 ret = -ENOMEM;
10074 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010076 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010077 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010078 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079 if (p_info == NULL) {
10080 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10081 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010082 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010083 ret = -EINVAL;
10084 goto done;
10085 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010087 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010088 *handle, p_info, patch_type, new_patch);
10089
10090 // Fetch stream info of associated mix for playback or capture patches
10091 if (p_info->patch_type == PATCH_PLAYBACK ||
10092 p_info->patch_type == PATCH_CAPTURE) {
10093 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10094 if (s_info == NULL) {
10095 ALOGE("%s: Failed to obtain stream info", __func__);
10096 if (new_patch)
10097 free(p_info);
10098 pthread_mutex_unlock(&adev->lock);
10099 ret = -EINVAL;
10100 goto done;
10101 }
10102 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10103 s_info->patch_handle = *handle;
10104 stream = s_info->stream;
10105 }
10106 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107
10108 // Update routing for stream
10109 if (stream != NULL) {
10110 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010111 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010112 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010113 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010114 if (ret < 0) {
10115 pthread_mutex_lock(&adev->lock);
10116 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10117 if (new_patch)
10118 free(p_info);
10119 pthread_mutex_unlock(&adev->lock);
10120 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10121 goto done;
10122 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010123 }
10124
10125 // Add new patch to patch map
10126 if (!ret && new_patch) {
10127 pthread_mutex_lock(&adev->lock);
10128 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010130 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010131 }
10132
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010133done:
10134 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010135 num_sources,
10136 sources,
10137 num_sinks,
10138 sinks,
10139 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010141 num_sources,
10142 sources,
10143 num_sinks,
10144 sinks,
10145 handle);
10146 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010147}
10148
10149int adev_release_audio_patch(struct audio_hw_device *dev,
10150 audio_patch_handle_t handle)
10151{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 struct audio_device *adev = (struct audio_device *) dev;
10153 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010154 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010155 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010156
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010157 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10158 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10159 ret = -EINVAL;
10160 goto done;
10161 }
10162
10163 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010164 pthread_mutex_lock(&adev->lock);
10165 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010166 if (p_info == NULL) {
10167 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010168 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010169 ret = -EINVAL;
10170 goto done;
10171 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010172 struct audio_patch *patch = p_info->patch;
10173 if (patch == NULL) {
10174 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010175 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010176 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010177 goto done;
10178 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010179 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10180 switch (patch->sources[0].type) {
10181 case AUDIO_PORT_TYPE_MIX:
10182 io_handle = patch->sources[0].ext.mix.handle;
10183 break;
10184 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010185 if (p_info->patch_type == PATCH_CAPTURE)
10186 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010187 break;
10188 case AUDIO_PORT_TYPE_SESSION:
10189 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010190 pthread_mutex_unlock(&adev->lock);
10191 ret = -EINVAL;
10192 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010193 }
10194
10195 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010196 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010197 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010198 if (patch_type == PATCH_PLAYBACK ||
10199 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010200 struct audio_stream_info *s_info =
10201 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10202 if (s_info == NULL) {
10203 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10204 pthread_mutex_unlock(&adev->lock);
10205 goto done;
10206 }
10207 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10208 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010209 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010210 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010211
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010212 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010213 struct listnode devices;
10214 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010215 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010216 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010217 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010218 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010219 }
10220
10221 if (ret < 0)
10222 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10223
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010224done:
10225 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10226 audio_extn_auto_hal_release_audio_patch(dev, handle);
10227
10228 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010229 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010230}
10231
10232int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10233{
Derek Chenf13dd492018-11-13 14:53:51 -080010234 int ret = 0;
10235
10236 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10237 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10238 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010239}
10240
10241int adev_set_audio_port_config(struct audio_hw_device *dev,
10242 const struct audio_port_config *config)
10243{
Derek Chenf13dd492018-11-13 14:53:51 -080010244 int ret = 0;
10245
10246 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10247 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10248 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010249}
10250
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010251static int adev_dump(const audio_hw_device_t *device __unused,
10252 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010253{
10254 return 0;
10255}
10256
10257static int adev_close(hw_device_t *device)
10258{
Aalique Grahame22e49102018-12-18 14:23:57 -080010259 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010260 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010261
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010262 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010263 return 0;
10264
10265 pthread_mutex_lock(&adev_init_lock);
10266
10267 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010268 if (audio_extn_spkr_prot_is_enabled())
10269 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010270 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010271 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010272 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010273 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010274 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010275 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010276 audio_extn_utils_release_streams_cfg_lists(
10277 &adev->streams_output_cfg_list,
10278 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010279 if (audio_extn_qap_is_enabled())
10280 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010281 if (audio_extn_qaf_is_enabled())
10282 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010283 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010284 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010285 free(adev->snd_dev_ref_cnt);
10286 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010287 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10288 pcm_params_free(adev->use_case_table[i]);
10289 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010290 if (adev->adm_deinit)
10291 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010292 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010293 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010294 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010295 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010296 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010297 if (adev->device_cfg_params) {
10298 free(adev->device_cfg_params);
10299 adev->device_cfg_params = NULL;
10300 }
Derek Chend2530072014-11-24 12:39:14 -080010301 if(adev->ext_hw_plugin)
10302 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010303 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010304 free_map(adev->patch_map);
10305 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010306 free(device);
10307 adev = NULL;
10308 }
10309 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010310 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010311 return 0;
10312}
10313
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010314/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10315 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10316 * just that it _might_ work.
10317 */
10318static int period_size_is_plausible_for_low_latency(int period_size)
10319{
10320 switch (period_size) {
10321 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010322 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010323 case 240:
10324 case 320:
10325 case 480:
10326 return 1;
10327 default:
10328 return 0;
10329 }
10330}
10331
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010332static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10333{
10334 bool is_snd_card_status = false;
10335 bool is_ext_device_status = false;
10336 char value[32];
10337 int card = -1;
10338 card_status_t status;
10339
10340 if (cookie != adev || !parms)
10341 return;
10342
10343 if (!parse_snd_card_status(parms, &card, &status)) {
10344 is_snd_card_status = true;
10345 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10346 is_ext_device_status = true;
10347 } else {
10348 // not a valid event
10349 return;
10350 }
10351
10352 pthread_mutex_lock(&adev->lock);
10353 if (card == adev->snd_card || is_ext_device_status) {
10354 if (is_snd_card_status && adev->card_status != status) {
10355 adev->card_status = status;
10356 platform_snd_card_update(adev->platform, status);
10357 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010358 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010359 if (status == CARD_STATUS_OFFLINE)
10360 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010361 } else if (is_ext_device_status) {
10362 platform_set_parameters(adev->platform, parms);
10363 }
10364 }
10365 pthread_mutex_unlock(&adev->lock);
10366 return;
10367}
10368
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010369/* adev lock held */
10370int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010371{
10372 struct audio_usecase *uc_info;
10373 float left_p;
10374 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010375 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010376
10377 uc_info = get_usecase_from_list(adev, out->usecase);
10378 if (uc_info == NULL) {
10379 ALOGE("%s: Could not find the usecase (%d) in the list",
10380 __func__, out->usecase);
10381 return -EINVAL;
10382 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010383 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010384
Zhou Song1f93fa52020-11-20 13:57:39 +080010385 ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__,
10386 out->usecase, use_case_table[out->usecase], out->a2dp_muted);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010387
10388 if (restore) {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010389 pthread_mutex_lock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010390 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010391 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010392 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010393 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10394 select_devices(adev, uc_info->id);
Zhou Song1f93fa52020-11-20 13:57:39 +080010395
10396 if (is_offload_usecase(out->usecase)) {
10397 if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010398 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
Zhou Song1f93fa52020-11-20 13:57:39 +080010399 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10400 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
10401 } else {
10402 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010403 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010404 out->a2dp_muted = false;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010405 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010406 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010407 } else {
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010408 pthread_mutex_lock(&out->latch_lock);
Zhou Song1f93fa52020-11-20 13:57:39 +080010409 // mute stream and switch to speaker if suspended
10410 if (!out->a2dp_muted && !out->standby) {
10411 ALOGD("%s: selecting speaker and muting stream", __func__);
10412 assign_devices(&devices, &out->device_list);
10413 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
10414 left_p = out->volume_l;
10415 right_p = out->volume_r;
10416 out->a2dp_muted = true;
10417 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010418 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10419 compress_pause(out->compr);
10420 out_set_compr_volume(&out->stream, (float)0, (float)0);
Zhou Song1f93fa52020-11-20 13:57:39 +080010421 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
10422 out_set_voip_volume(&out->stream, (float)0, (float)0);
10423 } else {
10424 out_set_pcm_volume(&out->stream, (float)0, (float)0);
10425 /* wait for stale pcm drained before switching to speaker */
10426 uint32_t latency =
10427 (out->config.period_count * out->config.period_size * 1000) /
10428 (out->config.rate);
10429 usleep(latency * 1000);
10430 }
10431 select_devices(adev, out->usecase);
10432 if (is_offload_usecase(out->usecase)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010433 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10434 compress_resume(out->compr);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010435 }
Zhou Song1f93fa52020-11-20 13:57:39 +080010436 assign_devices(&out->device_list, &devices);
10437 out->volume_l = left_p;
10438 out->volume_r = right_p;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010439 }
Weiyin Jiangd5974e62020-09-08 20:28:22 +080010440 pthread_mutex_unlock(&out->latch_lock);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010441 }
10442 ALOGV("%s: exit", __func__);
10443 return 0;
10444}
10445
Haynes Mathew George01156f92018-04-13 15:29:54 -070010446void adev_on_battery_status_changed(bool charging)
10447{
10448 pthread_mutex_lock(&adev->lock);
10449 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10450 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010451 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010452 pthread_mutex_unlock(&adev->lock);
10453}
10454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010455static int adev_open(const hw_module_t *module, const char *name,
10456 hw_device_t **device)
10457{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010458 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010459 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010460 char mixer_ctl_name[128] = {0};
10461 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010462
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010463 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010464 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10465
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010466 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010467 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010468 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010469 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010470 ALOGD("%s: returning existing instance of adev", __func__);
10471 ALOGD("%s: exit", __func__);
10472 pthread_mutex_unlock(&adev_init_lock);
10473 return 0;
10474 }
10475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010476 adev = calloc(1, sizeof(struct audio_device));
10477
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010478 if (!adev) {
10479 pthread_mutex_unlock(&adev_init_lock);
10480 return -ENOMEM;
10481 }
10482
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010483 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10484
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010485 // register audio ext hidl at the earliest
10486 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010487#ifdef DYNAMIC_LOG_ENABLED
10488 register_for_dynamic_logging("hal");
10489#endif
10490
Derek Chenf939fb72018-11-13 13:34:41 -080010491 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010492 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010493 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10494 maj_version = atoi(value);
10495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010496 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010497 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010498 adev->device.common.module = (struct hw_module_t *)module;
10499 adev->device.common.close = adev_close;
10500
10501 adev->device.init_check = adev_init_check;
10502 adev->device.set_voice_volume = adev_set_voice_volume;
10503 adev->device.set_master_volume = adev_set_master_volume;
10504 adev->device.get_master_volume = adev_get_master_volume;
10505 adev->device.set_master_mute = adev_set_master_mute;
10506 adev->device.get_master_mute = adev_get_master_mute;
10507 adev->device.set_mode = adev_set_mode;
10508 adev->device.set_mic_mute = adev_set_mic_mute;
10509 adev->device.get_mic_mute = adev_get_mic_mute;
10510 adev->device.set_parameters = adev_set_parameters;
10511 adev->device.get_parameters = adev_get_parameters;
10512 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10513 adev->device.open_output_stream = adev_open_output_stream;
10514 adev->device.close_output_stream = adev_close_output_stream;
10515 adev->device.open_input_stream = adev_open_input_stream;
10516 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010517 adev->device.create_audio_patch = adev_create_audio_patch;
10518 adev->device.release_audio_patch = adev_release_audio_patch;
10519 adev->device.get_audio_port = adev_get_audio_port;
10520 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010521 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010522 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010523
10524 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010525 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010526 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010527 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010528 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010529 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010530 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010531 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010532 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010533 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010534 /* Init audio and voice feature */
10535 audio_extn_feature_init();
10536 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010537 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010538 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010539 list_init(&adev->active_inputs_list);
10540 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010541 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010542 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10543 audio_extn_utils_hash_eq);
10544 if (!adev->io_streams_map) {
10545 ALOGE("%s: Could not create io streams map", __func__);
10546 ret = -ENOMEM;
10547 goto adev_open_err;
10548 }
10549 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10550 audio_extn_utils_hash_eq);
10551 if (!adev->patch_map) {
10552 ALOGE("%s: Could not create audio patch map", __func__);
10553 ret = -ENOMEM;
10554 goto adev_open_err;
10555 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010556 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010557 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010558 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010559 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010560 adev->perf_lock_opts[0] = 0x101;
10561 adev->perf_lock_opts[1] = 0x20E;
10562 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010563 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010564 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010565 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010566 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010567 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010568
Zhou Song68ebc352019-12-05 17:11:15 +080010569 audio_extn_perf_lock_init();
10570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010571 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010572 adev->platform = platform_init(adev);
10573 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010574 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010575 ret = -EINVAL;
10576 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010577 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010578
Aalique Grahame22e49102018-12-18 14:23:57 -080010579 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010580 if (audio_extn_qap_is_enabled()) {
10581 ret = audio_extn_qap_init(adev);
10582 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010583 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010584 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010585 }
10586 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10587 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10588 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010589
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010590 if (audio_extn_qaf_is_enabled()) {
10591 ret = audio_extn_qaf_init(adev);
10592 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010593 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010594 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010595 }
10596
10597 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10598 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10599 }
10600
Derek Chenae7b0342019-02-08 15:17:04 -080010601 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010602 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10603
Eric Laurentc4aef752013-09-12 17:45:53 -070010604 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10605 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10606 if (adev->visualizer_lib == NULL) {
10607 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10608 } else {
10609 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10610 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010611 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010612 "visualizer_hal_start_output");
10613 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010614 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010615 "visualizer_hal_stop_output");
10616 }
10617 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010618 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010619 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010620 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010621 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010622 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010623 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010624
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010625 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10626 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10627 if (adev->offload_effects_lib == NULL) {
10628 ALOGE("%s: DLOPEN failed for %s", __func__,
10629 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10630 } else {
10631 ALOGV("%s: DLOPEN successful for %s", __func__,
10632 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10633 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010634 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010635 "offload_effects_bundle_hal_start_output");
10636 adev->offload_effects_stop_output =
10637 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10638 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010639 adev->offload_effects_set_hpx_state =
10640 (int (*)(bool))dlsym(adev->offload_effects_lib,
10641 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010642 adev->offload_effects_get_parameters =
10643 (void (*)(struct str_parms *, struct str_parms *))
10644 dlsym(adev->offload_effects_lib,
10645 "offload_effects_bundle_get_parameters");
10646 adev->offload_effects_set_parameters =
10647 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10648 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010649 }
10650 }
10651
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010652 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10653 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10654 if (adev->adm_lib == NULL) {
10655 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10656 } else {
10657 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10658 adev->adm_init = (adm_init_t)
10659 dlsym(adev->adm_lib, "adm_init");
10660 adev->adm_deinit = (adm_deinit_t)
10661 dlsym(adev->adm_lib, "adm_deinit");
10662 adev->adm_register_input_stream = (adm_register_input_stream_t)
10663 dlsym(adev->adm_lib, "adm_register_input_stream");
10664 adev->adm_register_output_stream = (adm_register_output_stream_t)
10665 dlsym(adev->adm_lib, "adm_register_output_stream");
10666 adev->adm_deregister_stream = (adm_deregister_stream_t)
10667 dlsym(adev->adm_lib, "adm_deregister_stream");
10668 adev->adm_request_focus = (adm_request_focus_t)
10669 dlsym(adev->adm_lib, "adm_request_focus");
10670 adev->adm_abandon_focus = (adm_abandon_focus_t)
10671 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010672 adev->adm_set_config = (adm_set_config_t)
10673 dlsym(adev->adm_lib, "adm_set_config");
10674 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10675 dlsym(adev->adm_lib, "adm_request_focus_v2");
10676 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10677 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10678 adev->adm_on_routing_change = (adm_on_routing_change_t)
10679 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010680 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10681 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010682 }
10683 }
10684
Aalique Grahame22e49102018-12-18 14:23:57 -080010685 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010686 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010687 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010688 //initialize this to false for now,
10689 //this will be set to true through set param
10690 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010691
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010692 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010693 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010694
10695 if (k_enable_extended_precision)
10696 adev_verify_devices(adev);
10697
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010698 adev->dsp_bit_width_enforce_mode =
10699 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010700
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010701 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10702 &adev->streams_output_cfg_list,
10703 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010704
Kiran Kandi910e1862013-10-29 13:29:42 -070010705 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010706
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010707 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010708 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010709 trial = atoi(value);
10710 if (period_size_is_plausible_for_low_latency(trial)) {
10711 pcm_config_low_latency.period_size = trial;
10712 pcm_config_low_latency.start_threshold = trial / 4;
10713 pcm_config_low_latency.avail_min = trial / 4;
10714 configured_low_latency_capture_period_size = trial;
10715 }
10716 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010717 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10718 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010719 trial = atoi(value);
10720 if (period_size_is_plausible_for_low_latency(trial)) {
10721 configured_low_latency_capture_period_size = trial;
10722 }
10723 }
10724
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010725 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10726
Eric Laurent4b084132018-10-19 17:33:43 -070010727 adev->camera_orientation = CAMERA_DEFAULT;
10728
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010729 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010730 af_period_multiplier = atoi(value);
10731 if (af_period_multiplier < 0)
10732 af_period_multiplier = 2;
10733 else if (af_period_multiplier > 4)
10734 af_period_multiplier = 4;
10735
10736 ALOGV("new period_multiplier = %d", af_period_multiplier);
10737 }
10738
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010739 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010740
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010741 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010742 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010743 pthread_mutex_unlock(&adev_init_lock);
10744
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010745 if (adev->adm_init)
10746 adev->adm_data = adev->adm_init();
10747
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010748 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010749 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010750
10751 audio_extn_snd_mon_init();
10752 pthread_mutex_lock(&adev->lock);
10753 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10754 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010755 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10756 /*
10757 * if the battery state callback happens before charging can be queried,
10758 * it will be guarded with the adev->lock held in the cb function and so
10759 * the callback value will reflect the latest state
10760 */
10761 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010762 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010763 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010764 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010765 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010766 /* Allocate memory for Device config params */
10767 adev->device_cfg_params = (struct audio_device_config_param*)
10768 calloc(platform_get_max_codec_backend(),
10769 sizeof(struct audio_device_config_param));
10770 if (adev->device_cfg_params == NULL)
10771 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010772
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010773 /*
10774 * Check if new PSPD matrix mixer control is supported. If not
10775 * supported, then set flag so that old mixer ctrl is sent while
10776 * sending pspd coefficients on older kernel version. Query mixer
10777 * control for default pcm id and channel value one.
10778 */
10779 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10780 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10781
10782 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10783 if (!ctl) {
10784 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10785 __func__, mixer_ctl_name);
10786 adev->use_old_pspd_mix_ctrl = true;
10787 }
10788
Eric Laurent994a6932013-07-17 11:51:42 -070010789 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010790 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010791
10792adev_open_err:
10793 free_map(adev->patch_map);
10794 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010795 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010796 pthread_mutex_destroy(&adev->lock);
10797 free(adev);
10798 adev = NULL;
10799 *device = NULL;
10800 pthread_mutex_unlock(&adev_init_lock);
10801 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010802}
10803
10804static struct hw_module_methods_t hal_module_methods = {
10805 .open = adev_open,
10806};
10807
10808struct audio_module HAL_MODULE_INFO_SYM = {
10809 .common = {
10810 .tag = HARDWARE_MODULE_TAG,
10811 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10812 .hal_api_version = HARDWARE_HAL_API_VERSION,
10813 .id = AUDIO_HARDWARE_MODULE_ID,
10814 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010815 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010816 .methods = &hal_module_methods,
10817 },
10818};